最近在看一本名叫《深刻淺出React和Redux》這一書,裏面談到了react的dom更新比對,記錄一下。javascript
假設有這麼一個組件java
<ul> <ListItem text="first" /> <ListItem text="second" /> <ListItem text="third" /> </ul>
如今,咱們在這個組件的前面插入一個新的組件<ListItem text='zero' />
react
<ul> <ListItem text="zero" /> <ListItem text="first" /> <ListItem text="second" /> </ul>
思考,怎麼更新dom是最優的,react是去怎麼更新?數組
按照咱們的思惟,最優的更新dom就是去把新增一個
ListItem
組件,放在第一個。把以前的第一個組件<ListItem text="first" />
以及第二個組件<ListItem text="second" />
日後挪一位。這樣的結果是最好的。dom
但是react不是這樣更新的!函數
它先去比較第一個
ListItem
組件,發現組件上的text
值first
變成了zero
,須要更新。第二個組件text
以前的second
變成了first
,也須要更新,最後新建立一個組件,把它的text
設置爲second
。react就完成了它的更新。code
在 React 的眼裏,肯定每個組件在組件序列中的惟一標識就是它的位置,因此
它也徹底不懂哪些子組件實際上並無改變,爲了讓 React 更加「聰明」,就須要開發者
提供一點幫助。ip
若是在代碼中明確地告訴 React 每一個組件的惟一標識,就能夠幫助 React 在處理這個
問題時聰明不少,告訴 React 每一個組件「身份證號」的途徑就是 key 屬性。開發
<ul> <ListItem key={1} text="first" /> <ListItem key={2} text="second" /> <ListItem key={3} text="third" /> </ul>
如今再去插入一個ListItem
組件放在最前面,讓它key爲0
it
<ul> <ListItem key={0} text="zero" /> <ListItem key={1} text="first" /> <ListItem key={2} text="second" /> </ul>
如今,react根據key值,知道了第二個第三個組件是以前的第一個第二個,因此react會建立一個ListItem
組件放在第一位,對於原有的兩個組件只用原有的props觸發更新。這裏就須要組件內部的shouldComponentUpdate
的鉤子函數進行判斷來減小沒必要要的更新。
可是這個 key 值只是惟一還不足夠,這個 key 值還須要是穩定不變的,試想,若是
key 值雖然可以在每一個時刻都惟一,可是變來變去,那麼就會誤導 React 作出錯誤判斷,
甚至致使錯誤的渲染結果。
<ul> { Arr.map((item,index)=>(<ListItem key={index} text={item.text} />)) } </ul>
用數組下標做爲 key ,看起來 key 值是惟一的,可是卻不是穩定不變的,隨着 Arr
數組值的不一樣,一樣一個Listltem
實例在不一樣的更新過程當中在數組中的下標徹底可能不
同,把下標當作 key 就讓 React 完全亂套了。
須要注意,雖然 key 是一個 prop ,可是接受 key 的組件並不能讀取到 key 的值,由於key
ref
React 保留的兩個特殊 prop ,並無預期讓組件直接訪問。