前言这里是官方的 Vue 特有代码的风格指南。如果在工程中使用 Vue,为了回避错误、小纠结和反模式,该指南是份不错的参考。

规则归类

优先级 A:必要这些规则会帮你规避错误,所以学习并接受它们带来的全部代价吧。这里面可能存在例外,但应该非常少,且只有你同时精通 JavaScript 和 Vue 才可以这样做。

优先级 B:推荐这些规则能够在绝大多数工程中改善可读性和开发体验。即使你违反了,代码还是能照常运行,但例外应该尽可能少且有合理的理由。

优先级 C:谨慎使用有些 Vue 特性的存在是为了照顾极端情况或帮助老代码的平稳迁移。当被过度使用时,这些特性会让你的代码难于维护甚至变成 bug 的来源。这些规则是为了给有潜在风险的特性敲个警钟,并说明它们什么时候不应该使用以及为什么。

优先级 A 的规则:必要的 (规避错误)

组件名为多个单词 必要组件名应该始终是多个单词的,根组件App 以及 、 之类的 Vue 内置组件除外。这样做可以避免跟现有的以及未来的 HTML 元素相冲突,因为所有的 HTML 元素名称都是单个单词的。

反例

Vue.component('todo', {

// ...

})export default {

name: 'Todo',

// ...

}

好例子

Vue.component('todo-item', {

// ...

})export default {

name: 'TodoItem',

// ...

}

组件数据 必要组件的data 必须是一个函数。当在组件中使用 data 属性的时候 (除了 newVue 外的任何地方),它的值必须是返回一个对象的函数。

详解当 data 的值是一个对象时,它会在这个组件的所有实例之间共享。想象一下,假如一个 TodoList 组件的数据是这样的:

data: {

listTitle: '',

todos: []

}我们可能希望重用这个组件,允许用户维护多个列表 (比如分为购物、心愿单、日常事务等)。这时就会产生问题。因为每个组件的实例都引用了相同的数据对象,更改其中一个列表的标题就会改变其它每一个列表的标题。增删改一个待办事项的时候也是如此。取而代之的是,我们希望每个组件实例都管理其自己的数据。为了做到这一点,每个实例必须生成一个独立的数据对象。在 JavaScript 中,在一个函数中返回这个对象就可以了:data: function () {

return {

listTitle: '',

todos: []

}

}

反例

Vue.component('some-comp', {

data: {

foo: 'bar'

}

})export default {

data: {

foo: 'bar'

}

}

好例子

Vue.component('some-comp', {

data: function () {

return {

foo: 'bar'

}

}

})// In a .vue file

export default {

data () {

return {

foo: 'bar'

}

}

}

// 在一个 Vue 的根实例上直接使用对象是可以的,

// 因为只存在一个这样的实例。

new Vue({

data: {

foo: 'bar'

}

})

Prop 定义 必要Prop 定义应该尽量详细。在你提交的代码中,prop 的定义应该尽量详细,至少需要指定其类型。

详解细致的 prop 定义有两个好处:它们写明了组件的 API,所以很容易看懂组件的用法;

在开发环境下,如果向一个组件提供格式不正确的 prop,Vue 将会告警,以帮助你捕获潜在的错误来源。

反例// 这样做只有开发原型系统时可以接受

props: ['status']

好例子

props: {

status: String

}// 更好的做法!

props: {

status: {

type: String,

required: true,

validator: function (value) {

return [

'syncing',

'synced',

'version-conflict',

'error'

].indexOf(value) !== -1

}

}

}

避免 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)。

详解当 Vue 处理指令时, v-for 比 v-if 具有更高的优先级,所以这个模板:

  • v-for='user in users'

    v-if='user.isActive'

    :key='user.id'

    >

    {{ user.name }}

将会经过如下运算:this.users.map(function (user) {

if (user.isActive) {

return user.name

}

})因此哪怕我们只渲染出一小部分用户的元素,也得在每次重渲染的时候遍历整个列表,不论活跃用户是否发生了变化。通过将其更换为在如下的一个计算属性上遍历:

computed: {

activeUsers: function () {

return this.users.filter(function (user) {

return user.isActive

})

}

}

  • v-for='user in activeUsers'

    :key='user.id'

    >

    {{ user.name }}

我们将会获得如下好处:过滤后的列表只会在 users 数组发生相关变化时才被重新运算,过滤更高效。

使用 v-for='user in activeUsers' 之后,我们在渲染的时候只遍历活跃用户,渲染更高效。

解藕渲染层的逻辑,可维护性 (对逻辑的更改和扩展) 更强。为了获得同样的好处,我们也可以把:

  • v-for='user in users'

    v-if='shouldShowUsers'

    :key='user.id'

    >

    {{ user.name }}

更新为:

  • v-for='user in users'

    :key='user.id'

    >

    {{ user.name }}

通过将 v-if 移动到容器元素,我们不会再对列表中的每个用户检查 shouldShowUsers。取而代之的是,我们只检查它一次,且不会在 shouldShowUsers 为否的时候运算 v-for。

反例

  • v-for='user in users'

    v-if='user.isActive'

    :key='user.id'

    >

    {{ user.name }}

  • v-for='user in users'

    v-if='shouldShowUsers'

    :key='user.id'

    >

    {{ user.name }}

好例子

  • v-for='user in activeUsers'

    :key='user.id'

    >

    {{ user.name }}

  • v-for='user in users'

    :key='user.id'

    >

    {{ user.name }}

优先级 B 的规则:推荐 (增强可读性)

组件文件 推荐只要有能够拼接文件的构建系统,就把每个组件单独分成文件。当你需要编辑一个组件或查阅一个组件的用法时,可以更快速的找到它。

反例

Vue.component('TodoList', {

// ...

})

Vue.component('TodoItem', {

// ...

})

好例子components/

|- TodoList.js

|- TodoItem.js

components/

|- TodoList.vue

|- TodoItem.vue

组件名中的单词顺序 推荐组件名应该以高级别的 (通常是一般化描述的) 单词开头,以描述性的修饰词结尾。要注意在你的应用中所谓的“高级别”是跟语境有关的。比如对于一个带搜索表单的应用来说,它可能包含这样的组件:components/

|- ClearSearchButton.vue

|- ExcludeFromSearchInput.vue

|- LaunchOnStartupCheckbox.vue

|- RunSearchButton.vue

|- SearchInput.vue

|- TermsCheckbox.vue你可能注意到了,我们很难看出来哪些组件是针对搜索的。现在我们来根据规则给组件重新命名:

components/

|- SearchButtonClear.vue

|- SearchButtonRun.vue

|- SearchInputExcludeGlob.vue

|- SearchInputQuery.vue

|- SettingsCheckboxLaunchOnStartup.vue

|- SettingsCheckboxTerms.vue因为编辑器通常会按字母顺序组织文件,所以现在组件之间的重要关系一目了然。你可能想换成多级目录的方式,把所有的搜索组件放到“search”目录,把所有的设置组件放到“settings”目录。我们只推荐在非常大型 (如有 100+ 个组件) 的应用下才考虑这么做,因为:在多级目录间找来找去,要比在单个 components 目录下滚动查找要花费更多的精力。

存在组件重名 (比如存在多个 ButtonDelete 组件) 的时候在编辑器里更难快速定位。

让重构变得更难,因为为一个移动了的组件更新相关引用时,查找/替换通常并不高效。

反例components/

|- ClearSearchButton.vue

|- ExcludeFromSearchInput.vue

|- LaunchOnStartupCheckbox.vue

|- RunSearchButton.vue

|- SearchInput.vue

|- TermsCheckbox.vue

好例子

components/

|- SearchButtonClear.vue

|- SearchButtonRun.vue

|- SearchInputQuery.vue

|- SearchInputExcludeGlob.vue

|- SettingsCheckboxTerms.vue

|- SettingsCheckboxLaunchOnStartup.vue

完整单词的组件名 推荐组件名应该倾向于完整单词而不是缩写。编辑器中的自动补全已经让书写长命名的代价非常之低了,而其带来的明确性却是非常宝贵的。不常用的缩写尤其应该避免。

反例components/

|- SdSettings.vue

|- UProfOpts.vue

好例子

components/

|- StudentDashboardSettings.vue

|- UserProfileOptions.vue

Prop 名大小写 推荐在声明 prop 的时候,其命名应该始终使用 camelCase,而在模板和 JSX 中应该始终使用 kebab-case。我们单纯的遵循每个语言的约定。在 JavaScript 中更自然的是 camelCase。而在 HTML 中则是 kebab-case。

反例props: {

'greeting-text': String

}

好例子

props: {

greetingText: String

}

多个特性的元素 推荐多个特性的元素应该分多行撰写,每个特性一行。在 JavaScript 中,用多行分隔对象的多个属性是很常见的最佳实践,因为这样更易读。模板和 JSX 值得我们做相同的考虑。

反例

好例子

src='https://vuejs.org/images/logo.png'

alt='Vue Logo'

>

foo='a'

bar='b'

baz='c'

/>

简单的计算属性 推荐应该把复杂计算属性分割为尽可能多的更简单的属性。

详解更简单、命名得当的计算属性是这样的:易于测试当每个计算属性都包含一个非常简单且很少依赖的表达式时,撰写测试以确保其正确工作就会更加容易。

易于阅读简化计算属性要求你为每一个值都起一个描述性的名称,即便它不可复用。这使得其他开发者 (以及未来的你) 更容易专注在他们关心的代码上并搞清楚发生了什么。

更好的“拥抱变化”任何能够命名的值都可能用在视图上。举个例子,我们可能打算展示一个信息,告诉用户他们存了多少钱;也可能打算计算税费,但是可能会分开展现,而不是作为总价的一部分。小的、专注的计算属性减少了信息使用时的假设性限制,所以需求变更时也用不着那么多重构了。

反例computed: {

price: function () {

var basePrice = this.manufactureCost / (1 - this.profitMargin)

return (

basePrice -

basePrice * (this.discountPercent || 0)

)

}

}

好例子

computed: {

basePrice: function () {

return this.manufactureCost / (1 - this.profitMargin)

},

discount: function () {

return this.basePrice * (this.discountPercent || 0)

},

finalPrice: function () {

return this.basePrice - this.discount

}

}

优先级 C 的规则:谨慎使用 (有潜在危险的模式)

没有在 v-if/ v-else-if/ v-else 中使用 key 谨慎使用如果一组v-if + v-else 的元素类型相同,最好使用 key (比如两个

元素)。默认情况下,Vue 会尽可能高效的更新 DOM。这意味着其在相同类型的元素之间切换时,会修补已存在的元素,而不是将旧的元素移除然后在同一位置添加一个新元素。如果本不相同的元素被识别为相同,则会出现意料之外的结果。

反例

错误:{{ error }}

{{ results }}

好例子

v-if='error'

key='search-status'

>

错误:{{ error }}

v-else

key='search-results'

>

{{ results }}

scoped 中的元素选择器 谨慎使用元素选择器应该避免在scoped 中出现。在 scoped 样式中,类选择器比元素选择器更好,因为大量使用元素选择器是很慢的。

详解为了给样式设置作用域,Vue 会为元素添加一个独一无二的特性,例如 data-v-f3f3eg9。然后修改选择器,使得在匹配选择器的元素中,只有带这个特性才会真正生效 (比如 button[data-v-f3f3eg9])。问题在于大量的元素和特性组合的选择器 (比如 button[data-v-f3f3eg9]) 会比类和特性组合的选择器慢,所以应该尽可能选用类选择器。

反例

X

button {

background-color: red;

}

好例子

X

.btn-close {

background-color: red;

}

隐性的父子组件通信 谨慎使用应该优先通过 prop 和事件进行父子组件之间的通信,而不是this.$parent 或改变 prop。一个理想的 Vue 应用是 prop 向下传递,事件向上传递的。遵循这一约定会让你的组件更易于理解。然而,在一些边界情况下 prop 的变更或 this.$parent 能够简化两个深度耦合的组件。问题在于,这种做法在很多简单的场景下可能会更方便。但请当心,不要为了一时方便 (少写代码) 而牺牲数据流向的简洁性 (易于理解)。

反例Vue.component('TodoItem', {

props: {

todo: {

type: Object,

required: true

}

},

template: ''

})

Vue.component('TodoItem', {

props: {

todo: {

type: Object,

required: true

}

},

methods: {

removeTodo () {

var vm = this

vm.$parent.todos = vm.$parent.todos.filter(function (todo) {

return todo.id !== vm.todo.id

})

}

},

template: `

{{ todo.text }}

X

`

})

好例子Vue.component('TodoItem', {

props: {

todo: {

type: Object,

required: true

}

},

template: `

:value='todo.text'

@input='$emit('input', $event.target.value)'

>

`

})

Vue.component('TodoItem', {

props: {

todo: {

type: Object,

required: true

}

},

template: `

{{ todo.text }}

X

`

})

非 Flux 的全局状态管理 谨慎使用应该优先通过 Vuex 管理全局状态,而不是通过this.$root 或一个全局事件总线。通过 this.$root 和/或全局事件总线管理状态在很多简单的情况下都是很方便的,但是并不适用于绝大多数的应用。Vuex 提供的不仅是一个管理状态的中心区域,还是组织、追踪和调试状态变更的好工具。

反例// main.js

new Vue({

data: {

todos: []

},

created: function () {

this.$on('remove-todo', this.removeTodo)

},

methods: {

removeTodo: function (todo) {

var todoIdToRemove = todo.id

this.todos = this.todos.filter(function (todo) {

return todo.id !== todoIdToRemove

})

}

}

})

好例子

// store/modules/todos.js

export default {

state: {

list: []

},

mutations: {

REMOVE_TODO (state, todoId) {

state.list = state.list.filter(todo => todo.id !== todoId)

}

},

actions: {

removeTodo ({ commit, state }, todo) {

commit('REMOVE_TODO', todo.id)

}

}

}

{{ todo.text }}

X

import { mapActions } from 'vuex'

export default {

props: {

todo: {

type: Object,

required: true

}

},

methods: mapActions(['removeTodo'])

}

https://github.com/vuejs/cn.vuejs.org/blob/master/src/v2/style-guide/index.md

vue修改编码_看,官方出品了 Vue 编码风格指南!相关推荐

  1. vue事件总线_[面试] 聊聊你对 Vue.js 框架的理解

    作者:yacan8 https://github.com/yacan8/blog/issues/26 本文为一次前端技术分享的演讲稿,所以尽力不贴 Vue.js 的源码,因为贴代码在实际分享中,比较枯 ...

  2. vue key重复_得心应用的Vue高级技巧

    关注 Vue中文社区,回复"加群"加入我们一起学习,天天进步1,require.context()一个webpack的api,通过执行require.context函数获取一个特定 ...

  3. 绝对编码和增量编码_用户体验设计师应该学习编码吗? 绝对

    绝对编码和增量编码 Even though I was trained as a graphic designer, I've never limited myself to that field e ...

  4. 手机号段对应地区编码_漫画:“哈夫曼编码” 是什么鬼?

    在上一期,我们介绍了一种特殊的数据结构 "哈夫曼树",也被称为最优二叉树.没看过的小伙伴可以点击下方链接: 漫画:什么是 "哈夫曼树" ? 那么,这种数据结构究 ...

  5. python转换字符编码_转:Python常见字符编码及其之间的转换

    一.Python常见字符编码 字符编码的常用种类介绍 第一种:ASCII码 ASCII(American Standard Code for Information Interchange,美国信息交 ...

  6. mysql 数据库编码怎么看_mysql如何查看数据库编码

    本文内容:本文介绍了在控制台下,使用命令的方式查看mysql数据库的编码. 1.首先连接数据库. 在cmd下输入 >mysql -h 数据库地址 -u 用户名 -p密码 2.连接数据库完成后 使 ...

  7. 火狐浏览器设置url编码_关于不同浏览器对URL编码的分析(转)

    转自:http://wdp107.iteye.com/blog/608786 先来看看三个url: url1. http://hi.baidu.com/爱宝的妍 url2. http://hi.bai ...

  8. python字符编码使用的是什么编码_不可不知的Python字符编码使用技巧(上)

    Python语言在网络爬虫领域应用的十分广泛.在爬虫的应用程序中,我们需要对网页上获取的数据进行处理,其中字符的编码.解码常常让人感到困惑:ASCII码.Unicode.字符编码什么的,很多朋友一直为 ...

  9. 2 snippets vue 修改配置_教你发布vue+.netCore项目到服务器

    最近一直在做项目,发布部署的事情都是同事或者老大做的,无奈什么事都要自己尝试经历后才能记住,所以发布的事情轮到我了,由于是第一次发布部署项目到一个新的服务器环境,难免会遇到各种各样的问题,总结下来,希 ...

  10. java修改默认字符编码_设置默认的Java字符编码?

    如何以编程方式正确设置JVM(1.5.x)使用​​的默认字符编码? 我已经读过-Dfile.encoding =以前是以往的方式去为旧的JVM -我没有那么奢侈的原因,我不会进入. 我努力了: Sys ...

最新文章

  1. python解释器环境中、用于表示上一次_大工20秋《数据挖掘》在线作业3 【标准答案】...
  2. leetcode算法题--Bulls and Cows
  3. eclipse Indigo Helios Galileo几种版本的意思
  4. Rider IDE恢复了对.NET Core调试的支持
  5. linux上安装memcached步骤
  6. 【Navicat】查看1000行以后的内容
  7. 站库网案例 B宝塔面板怎么建手机版子目录
  8. 使用sklearn不同方法在digits手写数字数据集上聚类并用matplotlib呈现
  9. 汽车故障检测仪计算机教程,如何使用汽车故障诊断仪进行汽车维修
  10. ant安装配置使用介绍及eclipse中使用
  11. Windows应用程序进阶2(非模态对话框 通用对话框)
  12. CoAP协议服务器,CoAP协议
  13. HTML+CSS静态页面网页设计作业——咖啡网站pc端带轮播js (5页) 学生酒水网页作业, 生鲜水果网页作业成品, 零食小吃网页作 美食网页业模板
  14. 计算机视觉-棋盘格标定
  15. 抄作业计算机叫,有种尴尬叫“抄作业”,答案是“B”抄成了13,抄错答案哄堂大笑...
  16. 浏览器打不开计算机二级网页,二级网页打不开,教您浏览器二级页面打不开怎么解决...
  17. 计算机技术在美术方面的应用,计算机技术在美术设计的应用
  18. PaddleSpeech 流式语音识别系统 PP-ASR
  19. 获取kvm的ip地址的三种方式
  20. 服务器存储面临的难题

热门文章

  1. Android布局基础知识
  2. android中工厂模式应用,抽象工厂模式在android中使用
  3. python立方体类_python学习12类
  4. oracle负数,oracle取交集_oracle取负数_oracle case when
  5. C/C++[codeup 2026]日期类
  6. 丢弃法(基于MXNet)
  7. 601. 体育馆的人流量
  8. 邻接矩阵(图的存储)
  9. HttpServlet介绍
  10. hadoop2.6.0的eclipse插件编译和设置