key概述
react中的key屬性棵譬,它是一個特殊的屬性株依,它的出現(xiàn)不是給開發(fā)者用的(例如你為一個組件設(shè)置key之后叉存,也仍無法獲取這個組件的key值)阎曹,而是給react自己用的。
簡單來說纵东,react利用key來識別組件粘招,它是一種身份標(biāo)識標(biāo)識,就像我們的身份證用來辨識一個人一樣偎球。每個key對應(yīng)一個組件洒扎,相同的key react認為是同一個組件,這樣后續(xù)相同的key對應(yīng)組件都不會被創(chuàng)建衰絮。
key的使用場景
在項目開發(fā)中袍冷,key屬性的使用場景最多的還是由數(shù)組動態(tài)創(chuàng)建的子組件
的情況,需要為每個子組件添加唯一的key屬性值
猫牡。那會有的人就會自然而然想到胡诗,key和動態(tài)渲染的子元素獲取的index位置的值很接近,那不是可以直接用index附上key的值呢key={index}?
例如:
{dataList.map((item,index)=>{
return <div style={mystyle} key={index}>{item.name}</div>
})
}
在你嘗試過后會發(fā)現(xiàn),報錯沒了煌恢,渲染也沒問題不是很正常嘛骇陈?!但是強烈不推薦用數(shù)組index來作為key
瑰抵。
如果數(shù)據(jù)更新僅僅是數(shù)組重新排序或在其中間位置插入新元素缩歪,那么視圖元素都將重新渲染。
例如:
本來index=2的元素向前移動后谍憔,那該元素的key不也同樣發(fā)生了改變那這樣會改變的Key就沒有任何的存在意義,既然是作為“身份證”一樣的存在主籍,那就不容有失习贫。當(dāng)然,在你用key值創(chuàng)建子組件的時候千元,若數(shù)組的內(nèi)容只是作為純展示苫昌,而不涉及到數(shù)組的動態(tài)變更,其實是可以使用index作為key的
幸海。
key的值必須保證唯一且穩(wěn)定
我在與Key值打過幾次交道過后祟身,覺得key值就類似于數(shù)據(jù)庫中的主鍵id
一樣,有且唯一
物独。
//this.state.users內(nèi)容袜硫。注意:李4和王5的id相同!5猜ā婉陷!
this.state = {
users: [{id:1,name: '張3'}, {id:2, name: '李4'}, {id: 2, name: "王5"}],
....//省略
}
render()
return(
<div>
<h3>用戶列表</h3>
{this.state.users.map(u => <div key={u.id}>{u.id}:{u.name}</div>)}
</div>
)
);
注意以上范例中,動態(tài)渲染的數(shù)據(jù)中官研,key以數(shù)據(jù)的id來定秽澳,而李4、王5的id相同而導(dǎo)致Key的雷同戏羽,最后的渲染結(jié)果為張3和李4担神,王5并沒有展示出來。主要是因為 react根據(jù)key認為李4和王5是同一個組件(李4和王5的key值相同)始花,導(dǎo)致第一個被渲染妄讯,后續(xù)的會被丟棄掉。
這樣衙荐,有了key屬性后捞挥,就可以與組件建立了一種對應(yīng)關(guān)系,react根據(jù)key來決定是銷毀重新創(chuàng)建組件還是更新組件
忧吟。
并且砌函,Key也要保證值的穩(wěn)定性
,例如:
{dataList.map((item,index)=>{
return <div style={mystyle} key={Math.random()}>{item.name}</div>
})
}
尤其如以上范例中所示,key的值以Math.random()隨機生成而定讹俊,這使得數(shù)組元素中的每項都重新銷毀然后重新創(chuàng)建垦沉,有一定的性能開銷;另外可能導(dǎo)致一些意想不到的問題出現(xiàn)仍劈。
所以厕倍,Key的值必須保證其唯一和穩(wěn)定性
所以,在不能使用random隨機生成key
時贩疙,我們可以像下面這樣用一個全局的counter變量來添加穩(wěn)定唯一的key值讹弯。
let counter = 1;
this.data.forEach(el=>{
el.id = counter++;
});
//向數(shù)組中動態(tài)添加元素時,
function createUser(user) {
return {
...user,
id: counter++
}
}
key其它注意事項
當(dāng)然除了為數(shù)據(jù)元素生成的組件要添加key这溅,且key要穩(wěn)定且唯一之外组民,還需要注意以下幾點:
key屬性是添加到自定義的子組件上,而不是子組件內(nèi)部的頂層的組件上
悲靴。
//MyComponent
...
render() {//error
<div key={{item.key}}>{{item.name}}</div>
}
...
//right
<MyComponent key={{item.key}}/>
key值的唯一是有范圍的臭胜,即在數(shù)組生成的同級同類型的組件上要保持唯一
,而不是所有組件的key都要保持唯一
不僅僅在數(shù)組生成組件上癞尚,其他地方也可以使用key耸三,主要是react利用key來區(qū)分組件的,相同的key表示同一個組件浇揩,react不會重新銷毀創(chuàng)建組件實例仪壮,只可能更新;key不同胳徽,react會銷毀已有的組件實例睛驳,重新創(chuàng)建組件新的實例。
{
this.state.type ?
<div><Son_1/><Son_2/></div>
: <div><Son_2/><Son_1/></div>
}
例如上面代碼中膜廊,this.state.type的值改變時乏沸,原Son_1和Son2組件的實例都將會被銷毀,并重新創(chuàng)建Son_1和Son_2組件新的實例爪瓜,不能繼承原來的狀態(tài)蹬跃,其實他們只是互換了位置。為了避免這種問題铆铆,我們可以給組件加上key蝶缀。
{
this.state.type ?
<div><Son_1 key="1"/><Son_2 key="2"/></div>
: <div><Son_2 key="2" /><Son_1 key="1"/></div>
}
這樣,this.state.type的值改變時薄货,Son_1和Son2組件的實例沒有重新創(chuàng)建翁都,react只是將他們互換位置。