組件名應該始終是多個單詞的,根組件App
以及<transition>
、<component>
之類的 Vue 內置組件除外。css
這樣作能夠避免跟現有的以及將來的 HTML 元素相沖突,由於全部的 HTML 元素名稱都是單個單詞的。html
反例前端
Vue.component('todo', { // ... }) export default { name: 'Todo', // ... }
好例子vue
Vue.component('todo-item', { // ... }) export default { name: 'TodoItem', // ... }
組件的data
必須是一個函數。git
當在組件中使用data
屬性的時候 (除了new Vue
外的任何地方),它的值必須是返回一個對象的函數。github
反例web
Vue.component('some-comp', { data: { foo: 'bar' } })
export default { data: { foo: 'bar' } }
好例子vue-cli
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 的定義應該儘可能詳細,至少須要指定其類型。ide
反例
// 這樣作只有開發原型系統時能夠接受 props: ['status']
好例子
props: { status: String }
// 更好的作法! props: { status: { type: String, required: true, validator: function (value) { return [ 'syncing', 'synced', 'version-conflict', 'error' ].indexOf(value) !== -1 } } }
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 users" v-if="shouldShowUsers" :key="user.id" > {{ user.name }} </li> </ul>
好例子
<ul> <li v-for="user in activeUsers" :key="user.id" > {{ user.name }} </li> </ul>
<ul v-if="shouldShowUsers"> <li v-for="user in users" :key="user.id" > {{ user.name }} </li> </ul>
對於應用來講,頂級App
組件和佈局組件中的樣式能夠是全局的,可是其它全部組件都應該是有做用域的。
這條規則只和單文件組件有關。你_不必定_要使用scoped
attribute。設置做用域也能夠經過CSS Modules,那是一個基於 class 的相似BEM的策略,固然你也可使用其它的庫或約定。
無論怎樣,對於組件庫,咱們應該更傾向於選用基於 class 的策略而不是scoped
attribute。
這讓覆寫內部樣式更容易:使用了常人可理解的 class 名稱且沒有過高的選擇器優先級,並且不太會致使衝突。
反例
<template> <button class="btn btn-close">X</button> </template> <style> .btn-close { background-color: red; } </style>
好例子
<template> <button class="button button-close">X</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]">X</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">X</button> </template> <!-- 使用 BEM 約定 --> <style> .c-Button { border: none; border-radius: 2px; } .c-Button--close { background-color: red; } </style>
只要有可以拼接文件的構建系統,就把每一個組件單獨分紅文件。
當你須要編輯一個組件或查閱一個組件的用法時,能夠更快速的找到它。
反例
Vue.component('TodoList', { // ... }) Vue.component('TodoItem', { // ... })
好例子
components/ |- TodoList.js |- TodoItem.js
components/ |- TodoList.vue |- TodoItem.vue
單文件組件的文件名應該要麼始終是單詞大寫開頭 (PascalCase),要麼始終是橫線鏈接 (kebab-case)。
單詞大寫開頭對於代碼編輯器的自動補全最爲友好,由於這使得咱們在 JS(X) 和模板中引用組件的方式儘量的一致。然而,混用文件命名方式有的時候會致使大小寫不敏感的文件系統的問題,這也是橫線鏈接命名一樣徹底可取的緣由。
反例
components/ |- mycomponent.vue
components/ |- myComponent.vue
好例子
components/ |- MyComponent.vue
components/ |- my-component.vue
應用特定樣式和約定的基礎組件 (也就是展現類的、無邏輯的或無狀態的組件) 應該所有以一個特定的前綴開頭,好比Base
、App
或V
。
反例
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
只應該擁有單個活躍實例的組件應該以The
前綴命名,以示其惟一性。
這不意味着組件只可用於一個單頁面,而是_每一個頁面_只使用一次。這些組件永遠不接受任何 prop,由於它們是爲你的應用定製的,而不是它們在你的應用中的上下文。若是你發現有必要添加 prop,那就代表這其實是一個可複用的組件,_只是目前_在每一個頁面裏只使用一次。
反例
components/ |- Heading.vue |- MySidebar.vue
好例子
components/ |- TheHeading.vue |- TheSidebar.vue
和父組件緊密耦合的子組件應該以父組件名做爲前綴命名。
若是一個組件只在某個父組件的場景下有意義,這層關係應該體如今其名字上。由於編輯器一般會按字母順序組織文件,因此這樣作能夠把相關聯的文件排在一塊兒。
反例
components/ |- TodoList.vue |- TodoItem.vue |- TodoButton.vue
components/ |- SearchSidebar.vue |- NavigationForSearchSidebar.vue
好例子
components/ |- TodoList.vue |- TodoListItem.vue |- TodoListItemButton.vue
components/ |- SearchSidebar.vue |- SearchSidebarNavigation.vue
組件名應該以高級別的 (一般是通常化描述的) 單詞開頭,以描述性的修飾詞結尾。
反例
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
在單文件組件、字符串模板和JSX中沒有內容的組件應該是自閉合的——但在 DOM 模板裏永遠不要這樣作。
自閉合組件表示它們不只沒有內容,並且刻意沒有內容。其不一樣之處就好像書上的一頁白紙對比貼有「本頁有意留白」標籤的白紙。並且沒有了額外的閉合標籤,你的代碼也更簡潔。
不幸的是,HTML 並不支持自閉合的自定義元素——只有官方的「空」元素。因此上述策略僅適用於進入 DOM 以前 Vue 的模板編譯器可以觸達的地方,而後再產出符合 DOM 規範的 HTML。
反例
<!-- 在單文件組件、字符串模板和 JSX 中 --> <MyComponent></MyComponent>
<!-- 在 DOM 模板中 --> <my-component/>
好例子
<!-- 在單文件組件、字符串模板和 JSX 中 --> <MyComponent/>
<!-- 在 DOM 模板中 --> <my-component></my-component>
對於絕大多數項目來講,在單文件組件和字符串模板中組件名應該老是 PascalCase 的——可是在 DOM 模板中老是 kebab-case 的。
PascalCase 相比 kebab-case 有一些優點:
<MyComponent>
視覺上比<my-component>
更可以和單個單詞的 HTML 元素區別開來,由於前者的不一樣之處有兩個大寫字母,後者只有一個橫線。不幸的是,因爲 HTML 是大小寫不敏感的,在 DOM 模板中必須仍使用 kebab-case。
還請注意,若是你已是 kebab-case 的重度用戶,那麼與 HTML 保持一致的命名約定且在多個項目中保持相同的大小寫規則就可能比上述優點更爲重要了。在這些狀況下,在全部的地方都使用 kebab-case 一樣是能夠接受的。
反例
<!-- 在單文件組件和字符串模板中 --> <mycomponent/>
<!-- 在單文件組件和字符串模板中 --> <myComponent/>
<!-- 在 DOM 模板中 --> <MyComponent></MyComponent>
好例子
<!-- 在單文件組件和字符串模板中 --> <MyComponent/>
<!-- 在 DOM 模板中 --> <my-component></my-component>
或者
<!-- 在全部地方 --> <my-component></my-component>
JS/JSX中的組件名應該始終是 PascalCase 的,儘管在較爲簡單的應用中只使用Vue.component
進行全局組件註冊時,可使用 kebab-case 字符串。
反例
Vue.component('myComponent', { // ... })
import myComponent from './MyComponent.vue'
export default { name: 'myComponent', // ... }
export default { name: 'my-component', // ... }
好例子
Vue.component('MyComponent', { // ... })
Vue.component('my-component', { // ... })
import MyComponent from './MyComponent.vue'
export default { name: 'MyComponent', // ... }
組件名應該傾向於完整單詞而不是縮寫。
編輯器中的自動補全已經讓書寫長命名的代價很是之低了,而其帶來的明確性倒是很是寶貴的。不經常使用的縮寫尤爲應該避免。
反例
components/ |- SdSettings.vue |- UProfOpts.vue
好例子
components/ |- StudentDashboardSettings.vue |- UserProfileOptions.vue
在聲明 prop 的時候,其命名應該始終使用 camelCase,而在模板和JSX中應該始終使用 kebab-case。
咱們單純的遵循每一個語言的約定。在 JavaScript 中更天然的是 camelCase。而在 HTML 中則是 kebab-case。
反例
props: { 'greeting-text': String }
<WelcomeMessage greetingText="hi"/>
好例子
props: { greetingText: String }
<WelcomeMessage greeting-text\="hi"/>
多個 attribute 的元素應該分多行撰寫,每一個 attribute 一行。
在 JavaScript 中,用多行分隔對象的多個屬性是很常見的最佳實踐,由於這樣更易讀。模板和JSX值得咱們作相同的考慮。
反例
<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 } }
非空 HTML attribute 值應該始終帶引號 (單引號或雙引號,選你 JS 裏不用的那個)。
在 HTML 中不帶空格的 attribute 值是能夠沒有引號的,但這鼓勵了你們在特徵值裏_不寫_空格,致使可讀性變差。
反例
<input type=text>
<AppSidebar :style={width:sidebarWidth+'px'}>
好例子
<input type="text">
<AppSidebar :style="{ width: sidebarWidth + 'px' }">
指令縮寫 (用:
表示v-bind:
、用@
表示v-on:
和用#
表示v-slot:
) 應該要麼都用要麼都不用。
反例
<input v-bind:value="newTodoText" :placeholder="newTodoInstructions" >
<input v-on:input="onInput" @focus="onFocus" >
<template v-slot:header> <h1>Here might be a page title</h1> </template> <template #footer> <p>Here's some contact info</p> </template>
好例子
<input :value="newTodoText" :placeholder="newTodoInstructions" >
<input v-bind:value="newTodoText" v-bind:placeholder="newTodoInstructions" >
<input @input="onInput" @focus="onFocus" >
<input v-on:input="onInput" v-on:focus="onFocus" >
<template v-slot:header> <h1>Here might be a page title</h1> </template> <template v-slot:footer> <p>Here's some contact info</p> </template>
<template #header> <h1>Here might be a page title</h1> </template> <template #footer> <p>Here's some contact info</p> </template>