問題分析
- 相信大多數童鞋在使用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的核心就是——
React
的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,結果如下:
如圖 ,我們如果不用索引為key , 程式能快速的對比出差異,反之也能對出差異,但是必須對比整個虛擬DOM, 這樣,程式仍然能正常執行,只不過大大消耗了新舊虛擬DOM的對比的效能,並可能導致元件狀態問題。
- 所以,把索引設定為key值,可以嗎?
可以,但是不推薦這樣做,因為會大大消耗虛擬DOM的效能