一、虛擬 DOM 中 key 的作用
react/vue 中的 key 有什么作用?key的內(nèi)部原理是什么?
簡(jiǎn)單來(lái)說(shuō):
key 是虛擬 DOM 對(duì)象的標(biāo)識(shí),在更新顯示時(shí) key 起著極其重要的作用,提高渲染效率,防止渲染錯(cuò)誤。
詳細(xì)的說(shuō):
當(dāng)狀態(tài)中的數(shù)據(jù)發(fā)生變化時(shí),React 會(huì)根據(jù)【新數(shù)據(jù)】生成【新的虛擬DOM】
隨后 React 進(jìn)行【新虛擬DOM】與【舊虛擬DOM】的 diff 比較,比較規(guī)則如下:
1、【舊虛擬DOM】中找到了與【新虛擬DOM】相同的 key:
若虛擬 DOM 中內(nèi)容沒(méi)變,直接使用之前的真實(shí) DOM
若虛擬 DOM 中內(nèi)容變了,則生成新的真實(shí)DOM,隨后替換掉頁(yè)面中之前的真實(shí) DOM
2、舊虛擬DOM中未找到與新虛擬DOM相同的key
根據(jù)數(shù)據(jù)創(chuàng)建新的真實(shí) DOM,隨后渲染到到頁(yè)面
“就地復(fù)用” 策略:
當(dāng)數(shù)據(jù)項(xiàng)的順序發(fā)生改變時(shí),他不會(huì)移動(dòng)頁(yè)面上的 DOM 元素匹配數(shù)據(jù)項(xiàng)順序的改變,而是簡(jiǎn)單的復(fù)用此處的元素
如果綁定了 key 屬性,就可對(duì)當(dāng)前 DOM 元素進(jìn)行唯一標(biāo)識(shí),在進(jìn)行數(shù)據(jù)更新渲染時(shí),會(huì)基于 key 的變化重新排列 DOM 元素的順序
二、用 index 作為 key 可能會(huì)引發(fā)的問(wèn)題
界面效果沒(méi)問(wèn)題, 但效率低:
若對(duì)數(shù)據(jù)進(jìn)行,逆序添加、逆序刪除等破壞順序操作,會(huì)產(chǎn)生沒(méi)有必要的真實(shí) DOM 更新
慢動(dòng)作回放----使用 index 索引值作為 key
根據(jù) diffing 算法規(guī)則,所有 DOM 元素都需要都需要重生成新的真實(shí) DOM:
存在相同key 0 和 1,但虛擬 DOM內(nèi)容改成了,需要生成新的真實(shí) DOM;
新增key2,需要生成新的真實(shí) DOM。
初始數(shù)據(jù):
{ id: 1, name: '小張', age: 18 },
{ id: 2, name: '小李', age: 19 }
初始的虛擬 DOM:
<li key=0>小張---18</li>
<li key=1>小李---19</li>
更新后的數(shù)據(jù):
{ id: 3, name: '小王', age: 20 },
{ id: 1, name: '小張', age: 18 },
{ id: 2, name: '小李', age: 19 }
更新數(shù)據(jù)后的虛擬 DOM:
<li key=0>小王---20</li>
<li key=1>小張---18</li>
<li key=2>小李---19</li>
界面有問(wèn)題:
如果結(jié)構(gòu)中還包含輸入類(lèi)的 DOM,會(huì)產(chǎn)生錯(cuò)誤 DOM 更新
慢動(dòng)作回放----使用 index 索引值作為 key (界面有問(wèn)題)
根據(jù) diffing 算法規(guī)則,內(nèi)部 input “就地復(fù)用”策略順序會(huì)錯(cuò)亂
初始數(shù)據(jù):
{ id: 1, name: '小張', age: 18 },
{ id: 2, name: '小李', age: 19 }
初始的虛擬 DOM:
<li key=0>小張---18<input type="text"/></li>
<li key=1>小李---19<input type="text"/></li>
更新后的數(shù)據(jù):
{ id: 3, name: '小王', age: 20 },
{ id: 1, name: '小張', age: 18 },
{ id: 2, name: '小李', age: 19 }
更新數(shù)據(jù)后的虛擬 DOM:
<li key=0>小王---20<input type="text"/></li>
<li key=1>小張---18<input type="text"/></li>
<li key=2>小李---19<input type="text"/></li>
注意:
如果不存在對(duì)數(shù)據(jù)的逆序添加、逆序刪除等破壞順序操作,僅用于渲染列表用于展示,使用 index 作為 key 是沒(méi)有問(wèn)題的。
三、開(kāi)發(fā)中如何選擇key?
1、最好使用每條數(shù)據(jù)的唯一標(biāo)識(shí)作為 key , 比如 id、手機(jī)號(hào)、身份證號(hào)、學(xué)號(hào)等唯一值。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-724591.html
2、如果確定只是簡(jiǎn)單的展示數(shù)據(jù),用 index 也是可以的。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-724591.html
四、示例
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>key的作用</title>
</head>
<body>
<div id="test"></div>
<!-- 引入react核心庫(kù) -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
class Person extends React.Component {
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 (
<div>
<h2>展示人員信息</h2>
<button onClick={this.add}>添加一個(gè)小王</button>
<h3>使用index(索引值)作為key</h3>
<ul>
{
this.state.persons.map((personObj, index) => {
return <li key={index}>{personObj.name}---{personObj.age}<input type="text" /></li>
})
}
</ul>
<hr />
<hr />
<h3>使用id(數(shù)據(jù)的唯一標(biāo)識(shí))作為key</h3>
<ul>
{
this.state.persons.map((personObj) => {
return <li key={personObj.id}>{personObj.name}---{personObj.age}<input type="text" /></li>
})
}
</ul>
</div>
)
}
}
ReactDOM.render(<Person />, document.getElementById('test'))
</script>
</body>
</html>
到了這里,關(guān)于【10】基礎(chǔ)知識(shí):React - DOM的diffing算法的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!