跳轉到內容

優先順序A規則:不可或缺的

這些規則有助於防止錯誤,所以無論如何都要學習和遵守它們。例外情況可能存在,但應該非常罕見,並且只有那些對JavaScript和Vue都有專業知識的人才能做出。

使用多片語件名稱

使用者元件名稱應始終為多詞,除非是根App元件。這防止與現有和未來的HTML元素衝突,因為所有HTML元素都是單詞。

錯誤

template
<!-- in pre-compiled templates -->
<Item />

<!-- in in-DOM templates -->
<item></item>

正確

template
<!-- in pre-compiled templates -->
<TodoItem />

<!-- in in-DOM templates -->
<todo-item></todo-item>

使用詳細的屬性定義

在提交的程式碼中,屬性定義應儘可能詳細,至少指定型別。

詳細解釋

詳細的屬性定義有兩個優點

  • 它們記錄了元件的API,因此可以很容易地看到元件應該如何使用。
  • 在開發過程中,Vue會在元件提供格式不正確的屬性時警告你,幫助你捕獲潛在的錯誤來源。

錯誤

js
// This is only OK when prototyping
props: ['status']

正確

js
props: {
  status: String
}
js
// Even better!
props: {
  status: {
    type: String,
    required: true,

    validator: value => {
      return [
        'syncing',
        'synced',
        'version-conflict',
        'error'
      ].includes(value)
    }
  }
}

錯誤

js
// This is only OK when prototyping
const props = defineProps(['status'])

正確

js
const props = defineProps({
  status: String
})
js
// Even better!

const props = defineProps({
  status: {
    type: String,
    required: true,

    validator: (value) => {
      return ['syncing', 'synced', 'version-conflict', 'error'].includes(
        value
      )
    }
  }
})

使用帶鍵的v-for

keyv-for在元件中總是必須的,以便維護子樹內部元件狀態。即使對於元素,維護可預測的行為也是好的實踐,例如物件一致性在動畫中。

詳細解釋

假設你有一個待辦事項列表

js
data() {
  return {
    todos: [
      {
        id: 1,
        text: 'Learn to use v-for'
      },
      {
        id: 2,
        text: 'Learn to use key'
      }
    ]
  }
}
js
const todos = ref([
  {
    id: 1,
    text: 'Learn to use v-for'
  },
  {
    id: 2,
    text: 'Learn to use key'
  }
])

然後你按字母順序排序。當更新DOM時,Vue將最佳化渲染以執行最便宜的DOM突變。這可能意味著刪除第一個待辦事項元素,然後將其新增到列表的末尾。

問題是,有些情況下,不刪除將保留在DOM中的元素是很重要的。例如,你可能想使用<transition-group>來動畫化列表排序,或者如果渲染元素是<input>,則保持焦點。在這些情況下,為每個專案新增唯一的鍵(例如:key="todo.id")將告訴Vue如何更可預測地行為。

根據我們的經驗,最好始終新增唯一的鍵,這樣你和你的團隊就永遠不會擔心這些邊緣情況。然後在極少數效能關鍵的場景中,當物件一致性不是必需的時,你可以有意識地例外。

錯誤

template
<ul>
  <li v-for="todo in todos">
    {{ todo.text }}
  </li>
</ul>

正確

template
<ul>
  <li
    v-for="todo in todos"
    :key="todo.id"
  >
    {{ todo.text }}
  </li>
</ul>

避免在v-for中使用v-if

永遠不要在同一個元素上使用v-ifv-for>。

有兩種常見情況可能會讓人想這麼做

  • 在列表中過濾專案(例如,v-for="user in users" v-if="user.isActive")。在這些情況下,用返回過濾列表的新計算屬性(例如activeUsers)替換users

  • 為了避免隱藏列表時渲染列表(例如,v-for="user in users" v-if="shouldShowUsers")。在這些情況下,將v-if移動到容器元素(例如ulol)。

詳細解釋

當Vue處理指令時,v-if的優先順序高於v-for,所以這個模板

template
<ul>
  <li
    v-for="user in users"
    v-if="user.isActive"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

將丟擲錯誤,因為v-if指令將被首先評估,而迭代變數user在此刻不存在。

這可以透過迭代計算屬性來修復,如下所示

js
computed: {
  activeUsers() {
    return this.users.filter(user => user.isActive)
  }
}
js
const activeUsers = computed(() => {
  return users.filter((user) => user.isActive)
})
template
<ul>
  <li
    v-for="user in activeUsers"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

或者,我們可以使用帶有v-for<template>標籤來包裝<li>元素

template
<ul>
  <template v-for="user in users" :key="user.id">
    <li v-if="user.isActive">
      {{ user.name }}
    </li>
  </template>
</ul>

錯誤

template
<ul>
  <li
    v-for="user in users"
    v-if="user.isActive"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

正確

template
<ul>
  <li
    v-for="user in activeUsers"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>
template
<ul>
  <template v-for="user in users" :key="user.id">
    <li v-if="user.isActive">
      {{ user.name }}
    </li>
  </template>
</ul>

使用元件作用域樣式

對於應用來說,頂級App元件和佈局元件中的樣式可以是全域性的,但所有其他元件都應該始終具有作用域。

此內容僅適用於單檔案元件。它不要求使用scoped屬性。作用域可以透過CSS模組、基於類的策略,如BEM,或其他庫/約定來實現。

然而,元件庫應優先考慮基於類的策略,而不是使用scoped屬性。

這使得覆蓋內部樣式更加容易,使用人類可讀的類名,這些類名不具有過高的特定性,但仍非常不可能產生衝突。

詳細解釋

如果你正在開發一個大型專案,與其他開發者合作,或者有時包含第三方HTML/CSS(例如來自Auth0),一致的作用域將確保你的樣式僅應用於它們應該應用的元件。

除了scoped屬性之外,使用唯一的類名可以幫助確保第三方CSS不會應用於你的HTML。例如,許多專案使用buttonbtnicon類名,因此即使不使用BEM等策略,新增一個特定於應用程式和/或元件的字首(例如ButtonClose-icon)也可以提供一些保護。

錯誤

template
<template>
  <button class="btn btn-close">×</button>
</template>

<style>
.btn-close {
  background-color: red;
}
</style>

正確

template
<template>
  <button class="button button-close">×</button>
</template>

<!-- Using the `scoped` attribute -->
<style scoped>
.button {
  border: none;
  border-radius: 2px;
}

.button-close {
  background-color: red;
}
</style>
template
<template>
  <button :class="[$style.button, $style.buttonClose]">×</button>
</template>

<!-- Using CSS modules -->
<style module>
.button {
  border: none;
  border-radius: 2px;
}

.buttonClose {
  background-color: red;
}
</style>
template
<template>
  <button class="c-Button c-Button--close">×</button>
</template>

<!-- Using the BEM convention -->
<style>
.c-Button {
  border: none;
  border-radius: 2px;
}

.c-Button--close {
  background-color: red;
}
</style>
優先順序A規則:基本已載入