Vue 有个官方的风格指南,我从中摘抄了些认为比较重要、本身常忽略的点,加上一些分析列出来。也能够直接去观看风格指南: https://cn.vuejs.org/v2/style...
文件名要么是单词开头大写,要么是横线链接css
MyComponent.vue 或 my-component.vue
html
除了根组件或者布局组件,都要加上 scoped 设置做用域,避免影响其它地方的样式vue
v-for="user in users" v-if="user.isActive" /** 要换成 **/ v-for="user in activeUsers" computed () { return this.users.filter((item) => { return item.isActive }) } 好处: * 过滤后的列表_只_会在`users`数组发生相关变化时才被从新运算,过滤更高效。 * 使用`v-for="user in activeUsers"`以后,咱们在渲染的时候只遍历活跃用户,渲染更高效。 * 解耦渲染层的逻辑,可维护性 (对逻辑的更改和扩展) 更强。
v-for="user in users" v-if="shouldShowUsers" /** 要换成 **/ <ul v-if="shouldShowUsers"> <li v-for="user in users"></li> </ul> 好处: * 如上 * 经过将 v-if 移动到容器元素,咱们不会再对列表中的每一个用户检查 shouldShowUsers。取而代之的是,咱们只检查它一次,且不会在 shouldShowUsers 为否的时候运算 v-for。
prop 尽可能详细,不使用数组方式,而是用对象列出更多选项,至少须要指定其类型。git
好处:github
prop 应当使用 驼峰命名法,而在模板和 JSX 中使用时,要用横线链接(HTML 的约定)vuex
正确例子: <WelcomeMessage greeting-text="hi"/> props: { greetingText: String }
组件名始终应该是多个单词,避免和未来的 HTML 元素相冲突,例如数组
export default { // name: 'Todo',不推荐 name: 'TodoItem' }
对于不包含全局状态的(好比 vuex store)、展现类的、无逻辑或无状态的基础组件,例如 table、button、icon 等,应该都以一个特定的前缀开头,统一风格且与其余功能组件区分开来less
反例: components/ |- MyButton.vue |- VueTable.vue |- Icon.vue 正确例子: components/ |- BaseButton.vue |- BaseTable.vue |- BaseIcon.vue components/ |- AppButton.vue |- AppTable.vue |- AppIcon.vue components/ |- VButton.vue |- VTable.vue |- VIcon.vue
对于每一个页面只使用一次、不接受任何 prop (即内容写死了)的组件(例如顶部的公司 logo、底部的版权声明),要以 The 前缀命名,以示其惟一性编辑器
反例: components/ |- Heading.vue |- MySidebar.vue 正确例子: components/ |- TheHeading.vue |- TheSidebar.vue
对于和父组件紧密耦合的子组件(即只在指定的父组件里用到的),命名方式应该规范统一:父组件名+自己名字,由于编辑器一般会按字母顺序组织文件,因此这样作能够把相关联的文件排在一块儿。ide
注意:这里的父组件也是自定义组件
,例如自定义列表组件,其还有只在其自己使用的自定义列表 item 子组件、自定义按钮子组件,子组件命名要规范
如今一般作法(components 的父组件使用文件夹形式,包含 index.vue 和子组件文件夹): components/ |- TodoList/ |- Item/ |- index.vue |- Button.vue |- index.vue 或者单纯是命名上类似: components/ |- TodoList.vue |- TodoItem.vue |- TodoButton.vue 正确例子: components/ |- TodoList.vue |- TodoListItem.vue |- TodoListItemButton.vue components/ |- SearchSidebar.vue |- SearchSidebarNavigation.vue
对于没有内容的组件,在容许的状况下要使用自闭合形式,以提醒使用者它们不只没有内容,并且是刻意没有内容,且代码也更简洁。
容许的状况:单文件组件、字符串模板、JSX不容许的状况:DOM 模板(一些 HTML 元素中,例如 <ul>、<ol>、<table> 和 <select>,由于 HTML 不支持自闭合的自定义元素)
反例: <!-- 在单文件组件、字符串模板和 JSX 中 --> <MyComponent></MyComponent> <!-- 在 DOM 模板中 --> <my-component/> 正确例子: <!-- 在单文件组件、字符串模板和 JSX 中 --> <MyComponent/> <!-- 在 DOM 模板中 --> <my-component></my-component>
模板中组件名的书写方式,和文件的命名方式同样,要么是单词开头大写,要么是横线链接,二者不该该混用
还要注意,在 DOM 模板中,不支持单词大小写方式
,由于 HTML 是大小写不敏感的
正确例子: <!-- 在单文件组件和字符串模板中 --> <MyComponent/> <!-- 在 DOM 模板中 --> <my-component></my-component> 或者: <!-- 在全部地方 --> <my-component></my-component>
组件名应该用完整的单词,而不是缩写。不要为了减小名字的长度而用缩写(尤为是不经常使用的缩写),如今编辑器的自动补全功能已经让写长命名的代价很是低,而完整的命名带来的明确理解性是很是宝贵的。
反例: components/ |- SdSettings.vue |- UProfOpts.vue 正确例子: components/ |- StudentDashboardSettings.vue |- UserProfileOptions.vue
元素的多个 attribute 应该分多行,每一个 attribute 一行,更易读
反例: <img src="https://vuejs.org/images/logo.png" alt="Vue Logo"> <MyComponent foo="a" bar="b" baz="c"/> 正确例子: <img src="https://vuejs.org/images/logo.png" alt="Vue Logo" > <MyComponent foo="a" bar="b" baz="c" />
组件模板应该只包含简单的表达式,复杂的表达式应该重构为计算属性或方法
反例: {{ fullName.split(' ').map(function (word) { return word[0].toUpperCase() + word.slice(1) }).join(' ') }} 正确例子: <!-- 在模板中 --> {{ normalizedFullName }} // 复杂表达式已经移入一个计算属性 computed: { normalizedFullName: function () { return this.fullName.split(' ').map(function (word) { return word[0].toUpperCase() + word.slice(1) }).join(' ') } }
应该把复杂的计算属性分割成尽量多的更简单的计算属性。这样易于测试及阅读,且在将来若是其中某一属性须要被显示,就不须要重构了
反例: 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 } }
用 : 表示 v-bind:、用 @ 表示 v-on: 和用 # 表示 v-slot:,应该要么都用要么都不用。
在 scoped 的 scss/less/css 中,避免出现元素选择器,要使用 class 类选择器。
缘由:
为了给样式设置做用域,Vue 会为元素添加一个独一无二的 attribute,例如 data-v-f3f3eg9。而后修改选择器,使得在匹配选择器的元素中,只有带这个 attribute 才会真正生效 (好比 button[data-v-f3f3eg9])。问题在于大量的元素和 attribute 组合的选择器 (好比 button[data-v-f3f3eg9]) 会比类和 attribute 组合的选择器慢,因此应该尽量选用类选择器。
反例: <template> <button>X</button> </template> <style scoped> button { background-color: red; } </style> 正确例子: <template> <button class="btn btn-close">X</button> </template> <style scoped> .btn-close { background-color: red; } </style>
应该优先经过 prop 和事件进行父子组件之间的通讯,而不是 this.$parent 或变动 prop。
若是一组 v-if + v-else 的元素类型相同
,最好使用 key (好比两个 <div> 元素)。
默认状况下,Vue 会尽量高效的更新 DOM。这意味着其在相同类型的元素之间切换时,会修补已存在的元素,而不是将旧的元素移除而后在同一位置添加一个新元素。若是本不相同的元素被识别为相同,则会出现意料以外的结果。
以下代码,在按钮点击切换时,不会触发 transition 效果,由于它是在原本的 button 上进行修改,没有进行移除新增操做。在这里查看效果
反例: <transition> <button v-if="isEditing" v-on:click="isEditing = false"> Save </button> <button v-else v-on:click="isEditing = true"> Edit </button> </transition> <style> .v-enter-active, .v-leave-active { transition: all 1s; } .v-enter, .v-leave-to { opacity: 0; transform: translateY(30px); } .v-leave-active { position: absolute; } </style>
解决方法:
正确例子: <transition> <button v-if="isEditing" v-on:click="isEditing = false" key="save"> Save </button> <button v-else v-on:click="isEditing = true" key="edit"> Edit </button> </transition>