前置知識
Diffing算法:
- 每次做比較的時候最小的“粒度”是標簽(節(jié)點)漩氨;
- Diffing算法進行對比時是嵌套的;
虛擬DOM中key的作用:
1). 簡單的說:key是虛擬DOM對象的標識侨拦,在更新顯示時key起著極其重要的作用。
2). 詳細的說:當狀態(tài)中的數(shù)據(jù)發(fā)生變化時着撩,react會根據(jù)【新數(shù)據(jù)】生成【新的虛擬DOM】险毁,隨后React進行【新虛擬DOM】與【舊虛擬DOM】的diff比較:比較規(guī)則如下:
a. 舊虛擬DOM中找到了與新虛擬DOM相同的key:
(1). 若虛擬DOM中內(nèi)容沒變,直接使用之前的真實DOM
(2). 若虛擬DOM中內(nèi)容變了候引,則生成新的真實DOM,隨后替換掉頁面中之前的真實DOM
b. 舊虛擬DOM中未找到與新虛擬DOM相同的key敦跌,則根據(jù)數(shù)據(jù)創(chuàng)建的新的真實DOM澄干,隨后渲染到頁面。
用index作為key可能會引發(fā)的問題:
- 若對數(shù)據(jù)進行:逆序添加柠傍、逆序刪除等破壞順序操作:會產(chǎn)生沒有必要的真實DOM更新 ==> 頁面效果沒問題麸俘,但效率低,若數(shù)據(jù)量過大惧笛,則會造成頁面卡頓从媚、響應(yīng)慢。
- 如果結(jié)構(gòu)中還包含輸入類的DOM:會產(chǎn)生錯誤的DOM更新 ===> 頁面有問題患整。
- 如果僅是用于渲染列表展示拜效,則可以使用index作為key。
下面來看一段代碼示例:
state = {
persons: [
{id: 1, name: '小張', age: 18},
{id: 2, name: '小李', age: 19},
]
}
add = () => {
const { persons } = this.state;
const p = { id: persons.length + 1, name: '小王', age: 20 };
this.setState({
persons: [p, ...persons],
});
}
render() {
return (
<>
<button onClick={this.add}>添加一個小王</button>
<ul>
{
this.state.persons.map((ele, index) => {
return <div style={{ display: 'flex' }}><li key={index}>{ele.name}---{ele.age}</li><input /></div>
})
}
</ul>
</>
)
}
正是因為將 key設(shè)置為index各谚,導(dǎo)致出現(xiàn)了錯誤的DOM更新紧憾。