1. 程式人生 > >Vue: v-for的鍵值key

Vue: v-for的鍵值key

v-for中的key

       我們現在在使用v-for的時候,都必須會加上一個必要的key值,並且很多人會使用index來作為key,其實這樣是不太妥當的一種做法。那麼v-for中的鍵值key到底有什麼作用呢。

       首先看一看vue文件裡的說法:

      emmm,好像還是比較難懂,換種說法       在用v-for更新已渲染的元素列表的時候,會使用就地複用的策略;這就是說列表資料修改的時候,他會根據key值去判斷某個值是否修改,如果修改了就重新渲染,不然就複用之前的元素。

      總結一下,就是通過key值來提升渲染的效率。

      舉個?       

const list = [
    {
        id:1,
        name:'test'
    },
    {
        id:2,
        name:'test2',
    },
    {
        id:3,
        name:'test3'
    },
]
<div v-for="(item,index) in list :key="index">{{item.name}}</div>

這個場景在我們開發的時候經常會碰到,因為不加key,vue現在會直接報錯,所以我使用index作為key; 下面再舉兩個例子來看資料更新後的情況。

1.在最後一條資料後再加一條資料

const list = [
    {
        id: 1,
        name: 'test1',
    },
    {
        id: 2,
        name: 'test2',
    },
    {
        id: 3,
        name: 'test3',
    },
    {
        id: 4,
        name: '我是在最後新增的一條資料',
    },
]

此時前三條資料直接複用之前的,新渲染最後一條資料,此時用index作為key,沒有任何問題;

2.在中間插入一條資料

const list = [
    {
        id: 1,
        name: 'test1',
    },
    {
        id: 4,
        name: '我是插隊的一條資料',
    }
    {
        id: 2,
        name: 'test2',
    },
    {
        id: 3,
        name: 'test3',
    },
]

此時更新渲染資料,通過index定義的key去進行前後資料的對比,發現

之前的資料                         之後的資料

key: 0  index: 0 name: test1     key: 0  index: 0 name: test1
key: 1  index: 1 name: test2     key: 1  index: 1 name: 我是插隊的一條資料
key: 2  index: 2 name: test3     key: 2  index: 2 name: test2
                                 key: 3  index: 3 name: test3

 可以發現除了第一條資料可以複用以外,另外三條資料都需要重新渲染,因為key值發生了變化; 這時候就可以體現出了一個效率問題,只插入了一條資料,卻要重新渲染三條資料;

所以我們需要可以想辦法讓陣列中不會變化的資料的key值也不變,所以不能通過index來設定key值,應該設定一個唯一的id來標識資料的唯一性;我們修改之後再來對比一下渲染的效率:

之前的資料                         之後的資料

key: 1  id: 1 index: 0 name: test1     key: 1  id: 1 index: 0  name: test1
key: 2  id: 2 index: 1 name: test2     key: 4  id: 4 index: 1  name: 我是插隊的那條資料
key: 3  id: 3 index: 2 name: test3     key: 2  id: 2 index: 2  name: test2
                                       key: 3  id: 3 index: 3  name: test3

 對比可以發現,只有一條資料發生了變化,因為其他資料的id都沒變,所以key值也沒變,所以只需要渲染這一條新的資料即可 所以一般推薦使用id作為key值來配合v-for使用

下面大致從虛擬DOM的Diff演算法實現的角度去解釋一下:

vue和react的虛擬DOM的Diff演算法大致相同,其核心是基於兩個簡單的假設:

  1. 兩個相同的元件產生類似的DOM結構,不同的元件產生不同的DOM結構。
  2. 同一層級的一組節點,他們可以通過唯一的id進行區分。基於這兩點假設,使得虛擬DOM的Diff演算法的複雜度從O(n^3)降到了O(n)

 當某一層有很多相同的節點時,也就是列表節點時,Diff演算法的更新過程預設情況下也是遵循以上原則。 比如一下這個情況:

我們希望可以在B和C之間加一個F,Diff演算法預設執行起來是這樣的:

 

即把C更新成F,D更新成C,E更新成D,最後再插入E,很沒有效率

所以我們需要使用key來給每個節點做一個唯一識別符號,Diff演算法就可以正確的識別此節點,找到正確的位置區插入新的節點。

所以用一句話來概括,key的作用主要是為了高效的更新虛擬DOM。

參考