react列表渲染時為什么盡量不要把索引設置為key值


具體可見: https://juejin.im/post/6844904133430870024

在react中,如果要渲染一個列表,我們會用map()函數將數組循環處理然后渲染到DOM,在處理循環時,“key” 是一個你需要包含的特殊字符串屬性。

很多時候,我們會使用當前列表的索引為key,但這樣做真的好嗎?

要討論這個問題,我們要從react的原理說起,我們react的執行步驟一般是:用state和jsx模板生成虛擬DOM,然后用虛擬DOM生成真實的 DOM,當我們state發生變化時,render函數執行,生成新的 虛擬DOM,然后比較新舊虛擬DOM的區別,找到區別,然后直接操作DOM,改變有區別的內容,這樣比傳統的操作DOM,極大的提升了性能。

再說虛擬DOM,虛擬DOM其實就是一個JS對象(['div',{class:'app'},'item']),虛擬DOM核心之一是diff算法,diff算法的核心之一是同層對比,如圖:


 
同層對比

如果在第一層div時就有出現區別,那么對比結束,直接更新真實DOM中對應的當前節點,以此類推。。。

再說說key,假設我們在state中有一個列表[a,b,c],在遍歷渲染時用索引作為key,那么就是這樣:

a 0 b 1 c 2 

如果我們執行一個操作,點擊刪除數組中的a, 我們的列表就是[b,c],在遍歷渲染時仍然會用索引作為key,結果如下:

b 0 c 1 
 
區別

如圖 ,我們如果不用索引為key , 程序能快速的對比出差異,反之也能對出差異,但是必須對比整個虛擬DOM,
這樣,程序仍然能正常執行,只不過大大消耗了新舊虛擬DOM的對比的性能,並可能導致組件狀態問題。

 

再舉一個vue的例子:為什么不能用index作為key?

舉個栗子:

<template>
    <div v-for="(item, index) in list" :key="index" >{{item.name}}</div>
</template>
復制代碼
const list = [
    {
        id: 1,
        name: "Person1"
    },
    {
        id: 2,
        name: "Person2"
    },
    {
        id: 3,
        name: "Person3"
    },
    {
        id:4,
        name:"Person4"
    }
];
復制代碼

此時,刪除 “Person4” 是正常的,但是如果我刪除 “Person2” 就會出現問題。

刪除前

刪除后

這個時候,除了 Person1 之外,剩下的 Person3、Person4,因為被發現與相應 key 的綁定關系有變化,所以被重新渲染,這會影響性能。
如果此時 list 的 item 是 select 的選項,其中 Person3 是選中的,這個時候 Person2 被刪除了,用 index 作為 key 就會變成是 Person4 選中的了,這就產生了bug。

如果使用唯一id作為key,刪除 Person2 后,剩下的元素因為與 key 的關系沒有發生變化,都不會被重新渲染,從而達到提升性能的目的。此時,list 的 item 作為 select 的選項,也不會出現上面所描述的bug。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM