标准:组件名为多个单词
组件是通过组件名来调用的,所以组件名必须简短、富有含义并且具有可读性,应保持多个单词的来命名,根组件 App
除外。
这样做可以避免跟现有的以及未来的 HTML 元素,因为所有的 HTML 元素名称都是单个单词的。
组件的命名需遵从以下原则:
- 有意义的:不过于具体,也不过于抽象;
- 简短:2 到 3 个单词;
- 具有可读性: 以便于沟通交流;
推荐
<app-header></app-header>
<user-list></user-list>
<range-slider></range-slider>
<todo-item></todo-item>
不推荐
<!-- todo单个单词,不明确 -->
<todo></todo>
<!-- 虽然简短但是可读性差. 使用 `button-group` 替代 -->
<btn-group></btn-group>
<!-- ui 前缀太过于宽泛,在这里意义不明确 -->
<ui-slider></ui-slider>
<!-- 与自定义元素规范不兼容 -->
<slider></slider>
组件的 data
必须是一个函数。
当在组件中使用 data
属性的时候 (除了 new Vue
外的任何地方),它的值必须是返回一个对象的函数。因为当 data
的值是一个对象时,它会在这个组件的所有实例之间共享。
推荐
Vue.component('some-comp', {
data: function () {
return {
foo: 'bar'
}
}
})
// In a .vue file
export default {
data () {
return {
foo: 'bar'
}
}
}
// 在一个 Vue 的根实例上直接使用对象是可以的,
// 因为只存在一个这样的实例。
new Vue({
data: {
foo: 'bar'
}
})
不推荐
Vue.component('some-comp', {
data: {
foo: 'bar'
}
})
export default {
data: {
foo: 'bar'
}
}
Vue.js 的表达式是 Javascript 表达式,复杂的行内表达式难以阅读,那么可以使用 method 或是 computed 属性来替代其功能。
推荐
<template>
<h1>
{{ `${year}-${month}` }}
</h1>
</template>
<script type="text/javascript">
export default {
computed: {
month() {
return this.twoDigits((new Date()).getUTCMonth() + 1);
},
year() {
return (new Date()).getUTCFullYear();
}
},
methods: {
twoDigits(num) {
return ('0' + num).slice(-2);
}
},
};
</script>
不推荐
<template>
<h1>
{{ `${(new Date()).getUTCFullYear()}-${('0' + ((new Date()).getUTCMonth()+1)).slice(-2)}` }}
</h1>
</template>
v-for
设置键值标准:总是用 key 配合 v-for
在组件上总是必须用 key 配合 v-for,以便维护内部组件及其子树的状态。 在更新 DOM 的时候,Vue 将会优化渲染把可能的 DOM 变动降到最低。
推荐
<ul>
<li
v-for="todo in todos"
:key="todo.id">
{{ todo.text }}
</li>
</ul>
不推荐
<ul>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ul>
永远不要把 v-if 和 v-for 同时用在同一个元素上。
一般我们在两种常见的情况下会倾向于这样做:
① 为了过滤一个列表中的项目 (比如 v-for="user in users" v-if="user.isActive")。
在这种情形下,请将 users 替换为一个计算属性 (比如 activeUsers),让其返回过滤后的列表。
② 为了避免渲染本应该被隐藏的列表 (比如 v-for="user in users" v-if="shouldShowUsers")。
这种情形下,请将 v-if 移动至容器元素上 (比如 ul, ol)。
详情解释见
推荐
<ul>
<li
v-for="user in activeUsers"
:key="user.id">
{{ user.name }}
</li>
</ul>
<ul v-if="shouldShowUsers">
<li
v-for="user in users"
:key="user.id">
{{ user.name }}
</li>
</ul>
不推荐
<ul>
<li
v-for="user in users"
v-if="user.isActive"
:key="user.id">
{{ user.name }}
</li>
</ul>
<ul>
<li
v-for="user in users"
v-if="shouldShowUsers"
:key="user.id">
{{ user.name }}
</li>
</ul>
在插件、混入等扩展中始终为自定义的私有属性使用 $_ 前缀。并附带一个命名空间以回避和其它作者的冲突 (比如 $yourPluginName)。
推荐
var myGreatMixin = {
// ...
methods: {
$_myGreatMixin_update: function () {
// ...
}
}
}
不推荐
var myGreatMixin = {
// ...
methods: {
update: function () {
// ...
}
}
}
指令缩写 (用 : 表示 v-bind: 和 用 @ 表示 v-on:) 应该要么都用要么都不用。
不推荐
<input
v-bind:value="newTodoText"
:placeholder="newTodoInstructions">
<input
v-on:input="onInput"
@focus="onFocus">
推荐
<input
:value="newTodoText"
:placeholder="newTodoInstructions">
<input
v-bind:value="newTodoText"
v-bind:placeholder="newTodoInstructions">
<input
@input="onInput"
@focus="onFocus">
<input
v-on:input="onInput"
v-on:focus="onFocus">
在 Vue.js 组件上下文中,this指向了组件实例。因此当你切换到了不同的上下文时,要确保 this 指向一个可用的 component 变量。
换句话说,如果你正在使用 ES6 的话,就不要再编写 var self = this; 这样的代码了,您可以安全地使用 Vue 组件。
- 使用 ES6,就不再需要将 this 保存到一个变量中了。
- 一般来说,当你使用箭头函数时,会保留 this 的作用域。(箭头函数没有它自己的 this 值,箭头函数内的 this 值继承自外围作用域。)
- 如果你没有使用 ES6,当然也就不会使用 箭头函数 啦,那你必须将 “this” 保存到到某个变量中。这是唯一的例外。
不推荐
export default {
methods: {
hello() {
return 'hello';
},
printHello() {
const self = this; // 没有必要
console.log(self.hello());
},
},
}
推荐
export default {
methods: {
hello() {
return 'hello';
},
printHello() {
console.log(this.hello());
},
},
}
Mixins 封装可重用的代码,避免了重复。如果两个组件共享有相同的功能,则可以使用 mixin。
通过 mixin,你可以专注于单个组件的任务和抽象的通用代码。这有助于更好地维护你的应用程序。
移动端和桌面端的菜单组件,它们共享一些功能。我们可以抽象出这两个组件的核心功能到一个 mixin 中,例如:
const MenuMixin = {
data () {
return {
language: 'EN'
}
},
methods: {
changeLanguage () {
if (this.language === 'DE') this.$set(this, 'language', 'EN')
if (this.language === 'EN') this.$set(this, 'language', 'DE')
}
}
}
export default MenuMixin
要使用 mixin,只需将其导入到两个组件中(只展示移动组件)。
<template>
<ul class="mobile">
<li @click="changeLanguage">Change language</li>
</ul>
</template>
<script>
import MenuMixin from './MenuMixin'
export default {
mixins: [MenuMixin]
}
</script>
虽然 Vue.js 支持传递复杂的 JavaScript 对象通过 props 属性,但是应该尽可能的使用原始类型的数据。
尽量只使用JavaScript 原始类型(字符串、数字、布尔值) 和 函数,尽量避免复杂的对象。
props 的定义应该尽量详细,至少需要指定其类型。
组件props 原子化的好处:
- 使得组件 API 清晰直观;
- 只使用原始类型和函数作为 props ,使得组件的 API 更接近于 HTML(5) 原生元素;
- 其它开发者更好的理解每一个 prop 的含义和作用;
- 传递过于复杂的对象使得我们不能够清楚的知道哪些属性或方法被自定义组件使用,这使得代码难以重构和维护。
推荐
<range-slider
:values="[10, 20]"
min="0"
max="100"
step="5"
:on-slide="updateInputs"
:on-end="updateResults">
</range-slider
props: {
status: String
}
// 更好的做法!
props: {
max: {
type: Number, // 这里添加了数字类型的校验
default() { return 10; },
},
status: {
type: String,
required: true,
validator: function (value) {
return [
'syncing',
'synced',
'version-conflict',
'error'
].indexOf(value) !== -1
}
}
}
不推荐
<range-slider :config="complexConfigObject"></range-slider>
// 这样做只有开发原型系统时可以接受
props: ['status']
按照一定的结构组织,使得代码易于阅读和理解,同时也便于标准化。
推荐
<template>
<div class="Ranger">
<!-- ... -->
</div>
</template>
<script>
export default {
// name 属性
name: 'RangeSlider',
// 使用组件
components: {},
// 使用指令
directives: {},
// 使用过滤器
filters: {},
// 使用mixins 共享通用功能
mixins: [],
// 组成新的组件
extends: {},
// 组件属性、变量
props: {
bar: {}, // 按字母顺序
foo: {},
fooBar: {},
},
// 变量
data () {},
// 计算属性
computed: {},
// 响应式事件,监测方法
watch: {},
// 生命周期
beforeCreate () {},
created () {},
beforeMount () {},
mounted () {},
beforeUpdate () {},
updated () {},
activated () {},
deactivated () {},
beforeDestroy () {},
destroyed () {},
// 方法
methods: {}
}
</script>
<style scoped>
.Ranger { /* ... */ }
</style>
以上是根据与进行整理,更多风格规范请查阅两者文档