最近开始学习使用 Vue,在看完一遍官方文档,实践的过程当中发现有不少约定,特别是命名和引用组件的时候组件的名字,我都以为很奇怪,在看到这篇文章以后,说实话是被标题党了,以为能够经过别人总结的最佳实践来指导 Vue 的开发,可是看完以后确实对不少不理解的事情给了一个解释,也有不少的参考连接,下面就是原文翻译,想看原文点击html
各位开发者你们好, 在探索了一段时间的 VueJs 文档和 web 以后,为了更加正确的或更广泛易于接受的方式来使用 vuejs,建立了一个最佳实践和样式指南的列表。vue
下面的要点是与功能/优化相关的,其余的是关于 VueJs 命名约定和元素排序。更详细的信息能够在摘要中的连接中找到。git
$off
清除事件监听器当使用 $on
监听一个事件的时候,咱们应该始终记得在 destroyed()
方法中使用 $off
移除这个事件监听器,这是为了防止咱们产生内存泄漏。github
当发布或者监听一个自定义事件时,咱们应该始终使用 kebab-case(短横线命名法),为何?由于不管如何事件都会被自动转换成小写的形式,咱们永远不会在 camelCase(驼峰式) 或 PascalCase(帕斯卡命名法) 中监听事件,所以,以与监听事件相同的方式(使用 kebab-case)声明该事件更有意义。web
// Emitting
this.$emit('my-event') // instead of myEvent
// Listening
v-on:my-event
复制代码
watch
和 created
中调用同一个事件若是咱们须要在组件初始化和属性更新的时候触发一个方法,一般的作法是执行如下操做:api
watch: {
myProperty() {
this.doSomething();
}
},
created() {
this.doSomething();
},
methods: {
doSomething() {
console.log('doing something...');
}
},
复制代码
即便它看起来多是正确的,但在这里使用 created()
实际上是多余的。咱们能够将全部功能都放入 watch
,所以避免了必须在 created()
中重复代码而且依旧能够在组件初始化的时候触发这个方法。如:框架
watch: {
myProperty: {
immediate: true, // forcing handler on initial status
handler() {
this.doSomething();
}
}
},
methods: {
doSomething() {
console.log('doing something...');
}
},
// Even better solution
watch: {
myProperty: {
immediate: true, // forcing handler on initial status
handler() {
console.log('doing something...'); // No need to declare a function on methods for 1 use case
}
}
},
复制代码
v-for
循环中使用 :key
在你的模板循环中添加 :key
是一个常见的最佳实践,使用 v-for
的时候却不使用 :key
会致使难以发现错误,特别是在动画中。async
$_
前缀Mixins 是一种将重复代码放入一个块并根据须要将其导入屡次的好方法,可是(并且这是一个很大的转折),这可能会致使多个问题。从这一点讲,咱们将解决重叠属性的问题。编辑器
当咱们将一个 mixin
导入到组件中时,咱们正在将 mixin 代码与组件代码合并,如今,具备相同名称的属性会发生什么?组件将始终占据上风,组件的属性具备更高的优先级。ide
若是我但愿个人 mixin
拥有更高的优先级怎么办?您不能分配优先级,可是能够经过选择正确的命名约定来避免属性重叠甚至覆盖。 为了区分 mixin
属性和组件属性,咱们使用 $_
。为何使用这些符号?好吧,有这几个缘由:
VueJs
样式指南中的约定在 VueJs 风格指南中,您会发现他们建议加上 mixin
的名字,例如:$_myMixin_updateUser
。
我发现添加混入的名字会引发比可读性问题以外更多的混乱。但这也取决于 mixin
,上下文环境和开发人员。
经过添加一个简单的 $_
,像在 $_updateUser
中,我发现代码可读性更好,而且能够轻松地区分组件和Mixin。
mixin
中使用的内容应被限制在 mixin
中跟进上一点,mixins 还有另外一个问题:咱们忘记了内容(stuff)。
比方说,若是咱们建立一个使用 this.language
的 mixin,而且这个属性没有被定义或从 mixin
内部的商店中获取,则定义 mixin
的组件必须包含该 language
属性。
您已经知道,这很是容易出错。为了不这些错误,咱们在 mixin
自己内部获取了 mixin
所需的内容。没必要担忧咱们要抓两次内容, VueJs
很聪明,若是它检测到相同的内容已经从 Store
中获取到了,就不会作双重工做(由于大多数状况下都是从 Vuex 获取内容)
帕斯卡命名法与编辑器具备更好的集成,并在经常使用的 IDE 之间提供了更好的自动完成/导入功能。 若是要避免在不区分大小写的文件系统出现问题,能够考虑采用短横线命名法。
Presentational, dumb, or pure 组件须要使用前缀来和其余的 non pure 组件进行区分。这大大提升了项目的可读性以及团队和开发人员之间的知识传递。
在JavaScript中,帕斯卡命名法是类和原型构造函数的约定,这使 Vue 组件也使用帕斯卡命名法具备了意义。
若是咱们仅经过使用全局组件定义 Vue.component
,建议使用短横线命名法。
Prop
名称声明期间应始终使用 camelCase(驼峰命名法),但模板中使用 kebab-case(短横线命名法)遵循每种语言的约定:JavaScript (驼峰命名法)和HTML(短横线命名法),这使 prop
在 js 文件中使用驼峰命名法声明而且在 HTML 中使用短横线命名法具备了意义。
这看起来彷佛很乏味,可是在整个项目中查找组件和建立新的组件时,对整个项目中的组件的全部选项遵循相同的顺序会颇有帮助。
VueJs约定能够在样式指南中找到。
这是一个性能杀手,列表越大,这种不良实践将使更多性能受到影响。 让咱们用代码来解释,想象一下如下状况:
ul>
<li v-for="game in games" v-if="game.isActive" :key="game.slug" > {{ game.title }} <li> </ul> 复制代码
将会被像下面这样的方式进行执行:
this.games.map(function (game) {
if (game.isActive) {
return game.title
}
})
复制代码
咱们能够看到的是咱们会在整个 games
列表进行迭代,不管 game
的活动列表是否被更新。
在其余框架中,好比说 Angular,这种操做不会被编译(*ngIf不能在存在的同一元素中进行*ngFor)
Actions
必须有返回值这是在学习 async/await 和 Vuex actions 后所收获的。 请看如下示例:
// Store
[SOME_ACTION] () {
// Doing stuff that takes a while
console.log('Action done');
}
// Consuming action
async doSomething() {
await dispatch(SOME_ACTION);
console.log('Do stuff now');
}
This will output:
// Do stuff now
// Action done
复制代码
发生这种状况是由于 await
不知道该 await
什么,相反,若是咱们实际上返回一个 Promise.resolve()
,await
它将等待这个 resolve
而后继续执行。
// Store
[SOME_ACTION] () {
// Doing stuff that takes a while
console.log('Action done');
Promise.resolve();
}
// Consuming action
async doSomething() {
await dispatch(SOME_ACTION);
console.log('Do stuff now');
}
This will output:
// Action done
// Do stuff now
复制代码
actions
和 getters
里面使用选择器咱们之因此建立选择器,是有缘由的,它不只能够在整个应用程序中使用,并且能够在Vuex Store 中使用。 配合代码更好的理解:
// We have this selector
export const language = (state) => state.userConfig.language;
// In one of our actions, we need language:
// Bad
[GET_GAMES]({ commit, rootState }) {
const lang = rootState.userConfig.language;
// Do stuff...
}
// Good
[GET_GAMES]({ commit, rootState }) {
const lang = language(rootState);
// Do stuff...
}
复制代码
$off
清除事件监听器watch
和 created
中调用同一个事件v-for
循环中使用 :key
$_
前缀mixin
中使用的内容应被限制在 mixin
中Prop
名称声明期间应始终使用 camelCase(驼峰命名法),但模板中使用 kebab-case(短横线命名法)Actions
必须有返回值actions
和 getters
里面使用选择器