优先级 A 的规则:必要的 (规避错误)
这些规则有助于防止错误,因此不惜一切代价学习并遵守它们。例外情况可能存在,但应该非常罕见,并且只能由具有 JavaScript 和 Vue 专业知识的人员制作。
组件名为多个单词
组件名应该始终由多个单词组成,除了根组件App,以及<transition>、<component>之类的 Vue 内置组件。
这样做可以避免与现有以及未来的 HTML 元素产生冲突,因为所有的 HTML 元素名称都是单个单词的。
反面例子
<!-- in pre-compiled templates --> <Item /> <!-- in in-DOM templates --> <item></item>
正面例子
<!-- in pre-compiled templates --> <TodoItem /> <!-- in in-DOM templates --> <todo-item></todo-item>
Prop 定义应尽量详细
在提交的代码中,prop 的定义应该尽量详细,至少指定其类型。
反面例子
// This is only OK when prototyping props: ['status']
正面例子
props: {
status: String
}
// Even better!
props: {
status: {
type: String,
required: true,
validator: value => {
return [
'syncing',
'synced',
'version-conflict',
'error'
].includes(value)
}
}
}
为 v-for 设置 key 值
始终以v-for。在组件上必须始终以 key 配合 v-for,以便维护内部组件及其子树的状态。即使对于元素,维持可预测的行为也是一种好的做法。例如动画中的对象固化(object constancy)。
反面例子
<ul>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ul>
正面例子
<ul>
<li
v-for="todo in todos"
:key ="todo.id"
>
{{ 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 users"
v-if="user.isActive"
:key="user.id"
>
{{ user.name }}
</li>
</ul>
正面例子
<ul>
<li
v-for="user in activeUsers"
:key="user.id"
>
{{ user.name }}
</li>
</ul>
<ul> <templatev-for ="user in users" :key="user.id"> <liv-if ="user.isActive"> {{ user.name }} </li> </template> </ul>
为组件样式设置作用域
对于应用来说,样式在顶层 App 组件和布局组件中可以是全局的,但是在其它所有组件中都应该是有作用域的。
这条规则只适用于单文件组件。你不一定要使用
不管怎样,对于组件库来说,我们应该更倾向于选用基于 class 的策略,而不是
这会让覆写内部样式变得更容易:使用人类可理解的 class 名称,没有太高的选择器优先级,而且不太会导致冲突。
反面例子
<template>
<button class="btn btn-close">×</button>
</template>
<style>
.btn-close {
background-color: red;
}
</style>
正面例子
<template>
<button class="button button-close">×</button>
</template>
<!-- 使用 `scoped` attribute -->
<style scoped>
.button {
border: none;
border-radius: 2px;
}
.button-close {
background-color: red;
}
</style>
<template>
<button :class="[$style.button, $style.buttonClose]">×</button>
</template>
<!-- 使用 CSS modules -->
<style module>
.button {
border: none;
border-radius: 2px;
}
.buttonClose {
background-color: red;
}
</style>
<template>
<button class="c-Button c-Button--close">×</button>
</template>
<!-- 使用 BEM 约定 -->
<style>
.c-Button {
border: none;
border-radius: 2px;
}
.c-Button--close {
background-color: red;
}
</style>
私有 property 名称必要
使用模块作用域来确保外部无法访问到私有函数。如果无法做到这一点,就始终应该为插件、mixin 等不考虑对外公开 API 的自定义私有 property 使用$_前缀。并附带一个命名空间,以回避和其它作者的冲突(比如$_yourPluginName_)。
反面例子
const myGreatMixin = {
// ...
methods: {
update() {
// ...
}
}
}
const myGreatMixin = {
// ...
methods: {
_update() {
// ...
}
}
}
const myGreatMixin = {
// ...
methods: {
$update() {
// ...
}
}
}
const myGreatMixin = {
// ...
methods: {
$_update() {
// ...
}
}
}
正面例子
const myGreatMixin = {
// ...
methods: {
$_myGreatMixin_update() {
// ...
}
}
}
// Even better!
const myGreatMixin = {
// ...
methods: {
publicMethod() {
// ...
myPrivateFunction()
}
}
}
function myPrivateFunction() {
// ...
}
export default myGreatMixin
