VueJs best practices [译]

前言:

最近开始学习使用 Vue,在看完一遍官方文档,实践的过程当中发现有不少约定,特别是命名和引用组件的时候组件的名字,我都以为很奇怪,在看到这篇文章以后,说实话是被标题党了,以为能够经过别人总结的最佳实践来指导 Vue 的开发,可是看完以后确实对不少不理解的事情给了一个解释,也有不少的参考连接,下面就是原文翻译,想看原文点击html

正文

各位开发者你们好, 在探索了一段时间的 VueJs 文档和 web 以后,为了更加正确的或更广泛易于接受的方式来使用 vuejs,建立了一个最佳实践和样式指南的列表。vue

下面的要点是与功能/优化相关的,其余的是关于 VueJs 命名约定和元素排序。更详细的信息能够在摘要中的连接中找到。git

在组件被销毁的时候使用 $off 清除事件监听器

当使用 $on 监听一个事件的时候,咱们应该始终记得在 destroyed() 方法中使用 $off 移除这个事件监听器,这是为了防止咱们产生内存泄漏。github

事件命名须要使用 kebab-case(短横线命名法)命名

当发布或者监听一个自定义事件时,咱们应该始终使用 kebab-case(短横线命名法),为何?由于不管如何事件都会被自动转换成小写的形式,咱们永远不会在 camelCase(驼峰式) 或 PascalCase(帕斯卡命名法) 中监听事件,所以,以与监听事件相同的方式(使用 kebab-case)声明该事件更有意义。web

// Emitting
this.$emit('my-event') // instead of myEvent
// Listening
v-on:my-event
复制代码

避免在 watchcreated 中调用同一个事件

若是咱们须要在组件初始化和属性更新的时候触发一个方法,一般的作法是执行如下操做: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 使用 $_ 前缀

Mixins 是一种将重复代码放入一个块并根据须要将其导入屡次的好方法,可是(并且这是一个很大的转折),这可能会致使多个问题。从这一点讲,咱们将解决重叠属性的问题。编辑器

当咱们将一个 mixin 导入到组件中时,咱们正在将 mixin 代码与组件代码合并,如今,具备相同名称的属性会发生什么?组件将始终占据上风,组件的属性具备更高的优先级。ide

若是我但愿个人 mixin 拥有更高的优先级怎么办?您不能分配优先级,可是能够经过选择正确的命名约定来避免属性重叠甚至覆盖。 为了区分 mixin 属性和组件属性,咱们使用 $_。为何使用这些符号?好吧,有这几个缘由:

  1. VueJs 样式指南中的约定
  2. _ 是 Vue 的私密属性保留字
  3. $ 是 Vue 的生态系统保留字

VueJs 风格指南中,您会发现他们建议加上 mixin 的名字,例如:$_myMixin_updateUser

我发现添加混入的名字会引发比可读性问题以外更多的混乱。但这也取决于 mixin,上下文环境和开发人员。

经过添加一个简单的 $_,像在 $_updateUser 中,我发现代码可读性更好,而且能够轻松地区分组件和Mixin。

mixin 中使用的内容应被限制在 mixin

跟进上一点,mixins 还有另外一个问题:咱们忘记了内容(stuff)。

比方说,若是咱们建立一个使用 this.language 的 mixin,而且这个属性没有被定义或从 mixin内部的商店中获取,则定义 mixin的组件必须包含该 language 属性。

您已经知道,这很是容易出错。为了不这些错误,咱们在 mixin 自己内部获取了 mixin 所需的内容。没必要担忧咱们要抓两次内容, VueJs 很聪明,若是它检测到相同的内容已经从 Store 中获取到了,就不会作双重工做(由于大多数状况下都是从 Vuex 获取内容)

对单文件组件使用 PascalCase (帕斯卡命名法)或 kebab-case(短横线命名法)

帕斯卡命名法与编辑器具备更好的集成,并在经常使用的 IDE 之间提供了更好的自动完成/导入功能。 若是要避免在不区分大小写的文件系统出现问题,能够考虑采用短横线命名法。

对基础组件命名时使用前缀

Presentational, dumb, or pure 组件须要使用前缀来和其余的 non pure 组件进行区分。这大大提升了项目的可读性以及团队和开发人员之间的知识传递。

使用PascalCase(帕斯卡命名法)做为JS中的组件名称

在JavaScript中,帕斯卡命名法是类和原型构造函数的约定,这使 Vue 组件也使用帕斯卡命名法具备了意义。

若是咱们仅经过使用全局组件定义 Vue.component,建议使用短横线命名法。

Prop 名称声明期间应始终使用 camelCase(驼峰命名法),但模板中使用 kebab-case(短横线命名法)

遵循每种语言的约定:JavaScript (驼峰命名法)和HTML(短横线命名法),这使 prop 在 js 文件中使用驼峰命名法声明而且在 HTML 中使用短横线命名法具备了意义。

使用样式指南中规定的组件选项顺序

这看起来彷佛很乏味,可是在整个项目中查找组件和建立新的组件时,对整个项目中的组件的全部选项遵循相同的顺序会颇有帮助。

VueJs约定能够在样式指南中找到。

切勿在相同的元素上使用v-if,好比 v-for

这是一个性能杀手,列表越大,这种不良实践将使更多性能受到影响。 让咱们用代码来解释,想象一下如下状况:

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
复制代码

actionsgetters 里面使用选择器

咱们之因此建立选择器,是有缘由的,它不只能够在整个应用程序中使用,并且能够在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...
}
复制代码

总结

  1. 在组件被销毁的时候使用 $off 清除事件监听器
  2. 事件命名须要使用 kebab-case(短横线命名法)命名
  3. 避免在 watchcreated 中调用同一个事件
  4. 始终要在在 v-for 循环中使用 :key
  5. 为 Mixins 使用 $_ 前缀
  6. mixin 中使用的内容应被限制在 mixin
  7. 对单文件组件使用 PascalCase (帕斯卡命名法)或 kebab-case(短横线命名法)
  8. 对基础组件命名时使用前缀
  9. 使用PascalCase(帕斯卡命名法)做为JS中的组件名称 10. Prop 名称声明期间应始终使用 camelCase(驼峰命名法),但模板中使用 kebab-case(短横线命名法)
  10. 使用样式指南中规定的组件选项顺序
  11. 切勿在相同的元素上使用v-if,好比 v-for
  12. Actions 必须有返回值
  13. actionsgetters 里面使用选择器

参考连接

谢谢!

相关文章
相关标签/搜索