Stories

Detail Return Return

在 Vue 中為什麼不推薦用 index 做 key - Stories Detail

尤大在vue 2.x的文檔中明確指出:建議儘可能在使用 v-for 時提供 key attribute,除非遍歷輸出的 DOM 內容非常簡單,或者是刻意依賴默認行為以獲取性能上的提升。

尤大的建議説白了就是説:

如果index可以做key,那直接底層幫你傳進去好了,又何必讓你們多此一舉呢?乖乖的不要用index做key

那麼:key 到底有什麼用? 當 Vue.js 用 v-for 正在更新已渲染過的元素列表時,它默認用就地複用策略 。 這句話是什麼意思?

讓我們一起去探討吧

diff算法

image.png

簡單的説就是新舊虛擬dom的比較,如果有差異就以新的為準,然後再插入的真實的dom中,重新渲染

key的作用

image.png

一句話: key的作用主要是為了更高效的對比虛擬DOM中每個節點是否是相同節點;

舉個簡單的例子

三胞胎戰成一排,你怎麼知道誰是老大?

如果老大皮了一下子,和老三換了一下位置,你又如何區分出來?

給他們掛個牌牌,寫上老大、老二、老三。

這樣就不會認錯了。key就是這個作用。

通過 key 管理狀態

Vue 默認按照“就地更新”的策略來更新通過 v-for 渲染的元素列表。當數據項的順序改變時,Vue 不會隨之移動 DOM 元素的順序,而是就地更新每個元素,確保它們在原本指定的索引位置上渲染。

默認模式是高效的,但只適用於列表渲染輸出的結果不依賴子組件狀態或者臨時 DOM 狀態 (例如表單輸入值) 的情況

為了給 Vue 一個提示,以便它可以跟蹤每個節點的標識,從而重用和重新排序現有的元素,你需要為每個元素對應的塊提供一個唯一的 key attribute:

在沒有 key 的情況下,Vue 將使用一種最小化元素移動的算法,並儘可能地就地更新/複用相同類型的元素。如果傳了 key,則將根據 key 的變化順序來重新排列元素,並且將始終移除/銷燬 key 已經不存在的元素。

同一個父元素下的子元素必須具有唯一的 key。重複的 key 將會導致渲染異常

效率 & Bug

説到這,有些人就是認為是簡單的效率問題。

確實:設置key可以讓diff更高效,但僅僅是重繪重排嗎?

答案是否定

如果僅僅是效率低下,在操作極少的元素中,也無傷大雅。

但是,使用index帶來的問題卻要麻煩的多

image.png

image.png

<div id="app">
    <Child v-for="item,i in array" :text="item" @delete="remove(i)"/>
</div>

data() {
    return {
      array: [1, 2, 3]
    };
},
methods: {
    remove(i) {
      this.array.splice(i, 1);
    }
}
此時,key的作用就是為了複用。正是因為會複用,所以用index來做key會出現複用錯誤的問題, 造成意想不到的bug

總結

最簡單方便的就是:使用數據庫中的 id

如果返回值中沒有id怎麼辦

  • 創建一個自增id函數,每次調用自增一
  • 使用uuid庫

好了,就講到這裏了。期待你的一鍵三連

Add a new Comments

Some HTML is okay.