你不知道的React迴圈渲染時為什麼儘量不要把索引設定為key值?

薛定喵的諤發表於2019-04-10

問題分析

  • 相信大多數童鞋在使用React的時候,特別是遍歷渲染元素的時候,都見過下面這個 Warning

index.js:1446 Warning: Each child in a list should have a unique "key" prop.

  • 所以我都會習慣性的給 item 指定一個 key , 而有的時候為了方便我們會直接把list 的索引指定成key,但是這樣所並不被推薦,那這是為什麼呢?

刨根問底

我們知道react的執行步驟一般是:

  • 用state和jsx模板生成虛擬DOM,然後用虛擬DOM生成真實的 DOM,當我們state發生變化時,render函式執行,生成新的 虛擬DOM,然後比較新舊虛擬DOM的區別,找到區別,然後直接操作DOM,改變有區別的內容,這樣比傳統的操作DOM,極大的提升了效能。

  • 而虛擬DOM的核心就是——Reactdiff演算法,要搞清楚這個問題我們首先要來看看 diff演算法

diff演算法

我們從上圖可以看出React 在更新虛擬DOM的時候是逐層往下的,也就是說第一層div時就有出現區別,那麼對比結束,直接更新真實DOM中對應的當前節點,以此類推。

Solve the problem

  • 好! 現在我們可以來看看 這個key了,假設我們在state中有一個列表[A,B,C],在遍歷渲染時用索引作為key,那麼就是這樣的.
A 0
B 1
C 2
複製程式碼

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

diff2

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

  • 所以,把索引設定為key值,可以嗎? 可以,但是不推薦這樣做,因為會大大消耗虛擬DOM的效能

相關文章