一、组件命名
- 组件名为多个单词
组件是通过组件名来调用的,所以组件名必须简短、富有含义并且具有可读性,应保持多个单词的来命名,根组件 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.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
总是用 key 配合 v-for 在组件上总是必须用 key 配合 v-for,以便维护内部组件及其子树的状态。 在更新 DOM 的时候,Vue 将会优化渲染把可能的 DOM 变动降到最低。
推荐
<!-- key尽量使用数据的id 使用index会有一些问题-->
<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-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
:value="newTodoText"
:placeholder="newTodoInstructions">
<input
@input="onInput"
@focus="onFocus">
不推荐
<input
v-bind:value="newTodoText"
:placeholder="newTodoInstructions">
<input
v-on:input="onInput"
@focus="onFocus">
八、将 this 赋值给 component 变量
在 Vue.js 组件上下文中,this指向了组件实例。因此当你切换到了不同的上下文时,要确保 this 指向一个可用的 component 变量。
换句话说,如果你正在使用 ES6 的话,就不要再编写 var self = this; 这样的代码了,您可以安全地使用 Vue 组件。
使用 ES6,就不再需要将 this 保存到一个变量中了。
一般来说,当你使用箭头函数时,会保留 this 的作用域。(箭头函数没有它自己的 this 值,箭头函数内的 this 值继承自外围作用域。)
如果你没有使用 ES6,当然也就不会使用 箭头函数 啦,那你必须将 “this” 保存到到某个变量中。这是唯一的例外。
推荐
export default {
methods: {
hello() {
return 'hello';
},
printHello() {
console.log(this.hello());
}
}
}
不推荐
export default {
methods: {
hello() {
return 'hello';
},
printHello() {
const self = this; // 没有必要
console.log(self.hello());
},
},
}
九、尽可能使用 mixins
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>
十、组件结构化
按照一定的结构组织,使得代码易于阅读和理解,同时也便于标准化。
推荐
<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>