答案:主要是爲了提升同級的比較效率的。
借用我在博客上另外一篇 Vue 2 渲染過程的圖
其中核心比對邏輯就是新老節點頭對頭,頭對尾,尾對頭,尾對尾,都判定非 sameVnode,則拿着 key 去比對,若其中有被判定爲 sameVnode,則複用節點。反之需要刪除後再添加新節點。
function sameVnode(a, b) {
// key,tag,isComment相同,並且data都不爲空,並且節點類型不是input
return (
a.key === b.key && (
(
a.tag === b.tag &&
a.isComment === b.isComment &&
isDef(a.data) === isDef(b.data) &&
sameInputType(a, b)
) || (
isTrue(a.isAsyncPlaceholder) &&
a.asyncFactory === b.asyncFactory &&
isUndef(b.asyncFactory.error)
)
)
)
}
那麼有個問題,能複用節點一定就快嗎?不一定,設你需要渲染 10w 條列表數據
<li v-for="item in list" :key="item.id">{{ item.name }}</li>
list = [
{
id: 1,
name: 1
},
......
{
id: 100000,
name: 100000
}
]
若不寫 key,新老節點的 key 都是 undefined 相同。tag ,isComment相同,且 data 不爲空。那li 節點也都被判定爲 sameVnode,只需要迭代替換文本節點就可以了。
但若寫了 key,新老節點部分 key 不相同。判定爲 sameVnode 的部分照樣去替換文本節點,然而 key 不相同的部分還得創建/刪除 DOM 節點,花銷自然比不寫 key 大。
但這種場景只適用於簡單的無狀態組件,vue 還是推薦使用 key,這是因爲開發中遇到的大多數場景,都有自己的狀態。