优先级 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