外觀
優先順序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>
使用詳細的屬性定義
在提交的程式碼中,屬性定義應儘可能詳細,至少指定型別。
錯誤
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
key
與v-for
在元件中總是必須的,以便維護子樹內部元件狀態。即使對於元素,維護可預測的行為也是好的實踐,例如物件一致性在動畫中。
詳細解釋
假設你有一個待辦事項列表
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-if
和v-for>。
有兩種常見情況可能會讓人想這麼做
在列表中過濾專案(例如,
v-for="user in users" v-if="user.isActive"
)。在這些情況下,用返回過濾列表的新計算屬性(例如activeUsers
)替換users
。為了避免隱藏列表時渲染列表(例如,
v-for="user in users" v-if="shouldShowUsers"
)。在這些情況下,將v-if
移動到容器元素(例如ul
、ol
)。
詳細解釋
當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
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。例如,許多專案使用button
、btn
或icon
類名,因此即使不使用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>