1.react/vue中的key有什么作用?(key的內(nèi)部原理是什么)
(1)簡(jiǎn)單地說:key是虛擬DOM對(duì)象的標(biāo)識(shí)录粱,在更新顯示時(shí)key起著極其重要的作用
(2)詳細(xì)的說:當(dāng)狀態(tài)中的數(shù)據(jù)發(fā)生變化時(shí)杏死,react會(huì)根據(jù)【新數(shù)據(jù)】生成【新的虛擬DOM】摹芙,隨后React進(jìn)行【新虛擬DOM】與【舊虛擬DOM】的diff比較嵌莉,比較規(guī)則如下:
- 舊虛擬DOM找到了與新虛擬DOM相同的key:
若虛擬DOM中內(nèi)容沒變苛茂,直接使用之前的真實(shí)DOM
若虛擬DOM中內(nèi)容變了之宿,則生成新的真實(shí)DOM族操,隨后替換掉頁(yè)面中之前的真實(shí)DOM - 舊的虛擬DOM中未找到與新虛擬DOM相同的key
根據(jù)數(shù)據(jù)創(chuàng)建新的真實(shí)DOM,隨后渲染到頁(yè)面
2.為什么遍歷列表時(shí),key最好不要使用index
用index作為key可能引發(fā)的問題:
(1)若對(duì)數(shù)據(jù)進(jìn)行:逆序添加色难,逆序刪除等破壞順序操作
會(huì)產(chǎn)生沒有必要的真實(shí)DOM更新 ===> 界面效果沒問題泼舱,但是效率低
(2)如果結(jié)構(gòu)中還包括輸入類的DOM:
會(huì)產(chǎn)生錯(cuò)誤的DOM更新 ===> 界面有問題
(3)注意!如果不存在對(duì)數(shù)據(jù)的逆序添加枷莉,逆序刪除等破壞順序操作娇昙,
僅用于渲染列表用于展示,使用index作為key是沒有問題的
例:
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>
<h3>使用index(索引值)作為key</h3>
<button onClick={this.add}>添加一個(gè)小王</button>
<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"));
-
使用index索引作為key的程序執(zhí)行流程:
初始數(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 }
更新后的虛擬DOM
<li key=0>小王---20<input type="text"/></li> --->生成新的虛擬DOM,更新li中的內(nèi)容笤妙,但是復(fù)用了input <li key=1>小張---18<input type="text"/></li> --->生成新的虛擬DOM,更新li中的內(nèi)容冒掌,但是復(fù)用了input <li key=2>小李---19<input type="text"/></li> --->生成新的虛擬DOM,更新li中的內(nèi)容,并且添加了新的input
如果使用index作為key的值蹲盘,且新添加的內(nèi)容在數(shù)組的前面股毫,則每次的更新都不會(huì)復(fù)用上一次的虛擬DOM,增加程序開銷
-
使用id唯一標(biāo)識(shí)作為key
初始數(shù)據(jù)
{ id: 1, name: "小張", age: 18 }, { id: 2, name: "小李", age: 19 }
初始虛擬DOM
<li key=1>小張---18<input type="text"/></li> <li key=2>小李---19<input type="text"/></li>
更新后的數(shù)據(jù)
{ id: 3, name: "小王", age: 20 }, { id: 1, name: "小張", age: 18 }, { id: 2, name: "小李", age: 19 }
更新后的虛擬DOM
<li key=3>小王---20<input type="text"/></li> --->生成新的虛擬DOM,更新li中的內(nèi)容召衔,并且添加了新的input <li key=1>小張---18<input type="text"/></li> --->復(fù)用原來的li中的內(nèi)容及input <li key=2>小李---19<input type="text"/></li> --->復(fù)用原來的li中的內(nèi)容及input
3.開發(fā)中如何選擇key?
(1)最好使用每條數(shù)據(jù)的唯一標(biāo)識(shí)作為key铃诬,比如id、手機(jī)號(hào)苍凛、身份證號(hào)趣席、學(xué)號(hào)等唯一值
(2)如果確定只是簡(jiǎn)單的展示數(shù)據(jù),用index也是可以的