vue 官方風格指南解析

Vue 有個官方的風格指南,我從中摘抄了些認爲比較重要、本身常忽略的點,加上一些分析列出來。也能夠直接去觀看風格指南: https://cn.vuejs.org/v2/style...

單文件組件文件的命名

文件名要麼是單詞開頭大寫,要麼是橫線鏈接css

MyComponent.vue 或 my-component.vuehtml

爲組件樣式設置做用域

除了根組件或者佈局組件,都要加上 scoped 設置做用域,避免影響其它地方的樣式vue

永遠不要把 v-if 和 v-for 同時用在同一個元素上

  • 若是要過濾列表,使其隱藏不符合條件的項目,可使用計算屬性,預先篩選出符合條件的數組
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-if 移到外層容器元素上
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 定義

prop 儘可能詳細,不使用數組方式,而是用對象列出更多選項,至少須要指定其類型。git

好處:github

  • 它們寫明瞭組件的 API,因此很容易看懂組件的用法;
  • 在開發環境下,若是向一個組件提供格式不正確的 prop,Vue 將會告警,以幫助你捕獲潛在的錯誤來源。

Prop 名格式

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 應該分多行,每一個 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 中的元素選擇器

在 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-if/v-else 中使用 key

若是一組 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>
相關文章
相關標籤/搜索