可以唯一的確定一個DOM元素,讓diff算法更加高效
<body>
<div id='app'>
<p v-for='item in items' :key='item'>{{item}}</p>
</div>
<script>
var vm = new Vue({
el:'#app'
data:{
items:['a','b','c','d','e']
}
mounted(){
setTimeout(()=>{
// 在c的前邊添加一個f
this.items.splice(2,0,'f')
},2000)
}
})
</script>
</body>
上邊案例重現(xiàn)的是以下過程
不使用key瘾敢,則 diff 算法默認是這樣的:
即把C更新成F祝辣,D更新成C,E更新成D涧团,最后再插入E只磷,是不是很沒有效率? 更新了3次泌绣,之后做了一次創(chuàng)建插入的操作
所以我們需要使用key來給每個節(jié)點做一個唯一標識钮追,Diff算法就可以正確的識別此節(jié)點,找到正確的位置區(qū)插入新的節(jié)點阿迈。
只使用了一次創(chuàng)建追加的操作
使用key
//首次循環(huán) patch A
A B C D E
A B F C D E
//第二次循環(huán) patch B
B C D E
B F C D E
//第三次循環(huán) patch E(首位找到相同節(jié)點)
C D E
F C D E
//第4次循環(huán) patch D
C D
F C D
//第5次循環(huán) patch C
C
F C
//oldCh全部處理結(jié)束元媚,newCh中剩下F,創(chuàng)建F并插入到C前邊
結(jié)論:
key 的作用主要是 為了實現(xiàn)高效的更新虛擬 DOM苗沧,提高性能刊棕。其原理是vue在patch的過程中通過key可以精準的判斷兩個節(jié)點是否是同一個,從而避免頻繁的更新元素崎页,使得整個patch過程更加高效鞠绰,減少DOM操作量,提高性能飒焦。
另外蜈膨,若不設置key,還可能在列表更新時引發(fā)一些隱蔽的bug牺荠。例如:
點擊第二項的delete翁巍,
原因很簡單,你認為你刪除了2休雌,但Vue會認為你做了兩件事:
- 把2變成了3
- 然后把3刪除了
- vue在使用相同的標簽名元素的過渡切換時灶壶,也會使用到key屬性,其目的也是為了讓vue可以區(qū)分它們杈曲,否則vue只會替換其內(nèi)部屬性而不會觸發(fā)過渡效果驰凛。
借用官方文檔上的例子:
<transition>
<span :key="text">{{text}}</span>
</transition>
這里如果text發(fā)生改變,整個<span>元素會發(fā)生更新担扑,因為當text改變時恰响,這個元素的key屬性就發(fā)生了改變,在渲染更新時涌献,Vue會認為這里新產(chǎn)生了一個元素胚宦,而老的元素由于key不存在了,所以會被刪除,從而觸發(fā)了過渡枢劝。
假如沒有key屬性:
<transition>
<span>{{text}}</span>
</transition>
那么當text改變時井联,Vue會復用元素,只改變<span>元素的內(nèi)容您旁,而不會有新的元素被添加進來烙常,也不會有舊的元素被刪除。
同理被冒,key屬性被用在組件上時军掂,當key改變時會引起新組件的創(chuàng)建和原有組件的刪除,此時組件的生命周期鉤子就會被觸發(fā)昨悼。