
v-for中key的作用
1.當(dāng)數(shù)據(jù)發(fā)生變化時(shí),vue是怎樣更新節(jié)點(diǎn)的?
渲染真實(shí)DOM的開銷是很大的,比如有時(shí)我們修改了某個(gè)數(shù)據(jù),如果直接渲染到真實(shí)dom上會(huì)引起整個(gè)dom樹的重繪和重排,有沒有可能我們只更新我們修改的那一小塊dom而不是更新整個(gè)dom呢?diff算法能夠幫助我們。
我們先根據(jù)真實(shí)DOM生成一顆virtual DOM,當(dāng)virtual DOM某個(gè)節(jié)點(diǎn)的數(shù)據(jù)改變后生成一個(gè)新的vnode,然后Vnode和oldVnode作對(duì)比,發(fā)現(xiàn)有不一樣的地方就直接修改在真實(shí)的DOM上,然后使oldVnode的值為Vnode。
2.virtual DOM和真實(shí)的DOM的區(qū)別
virtual DOM是將真實(shí)的DOM的數(shù)據(jù)抽取出來,以對(duì)象的形式模擬樹形結(jié)構(gòu)。比如dom是這樣的:
<div>
<p>123</p>
</div>
對(duì)應(yīng)的virtual DOM(偽代碼)
var Vnode={
tag:'div',
children:[
{tag:'p', text:'123'}
]
}
3.diff的比較方式
在采取diff算法比較新舊節(jié)點(diǎn)的時(shí)候,比較只會(huì)在同層進(jìn)行,不會(huì)跨層級(jí)比較。
<div>
<p>123</p>
</div>
<div>
<span>456</span>
</div>
大家要知道,不僅只是在vue中,react中在執(zhí)行列表渲染時(shí)也會(huì)要求給每個(gè)組件添加key這個(gè)屬性。如果想知道key的作用,我們就得聊一下虛擬DOM的Diff算法
參考文章:深度剖析:如何實(shí)現(xiàn)一個(gè) Virtual DOM算法
所謂虛擬DOM的誕生,使我們可以不直接操作DOM元素,只操作數(shù)據(jù)便可以重新渲染頁面。而隱藏在背后的原理便是其高效的Diff算法,它的核心是基于兩個(gè)簡單的假設(shè):
1.兩個(gè)相同的組件產(chǎn)生類似的DOM結(jié)構(gòu),不同的組件產(chǎn)生不同的DOM結(jié)構(gòu)
2.同一個(gè)層級(jí)的一組節(jié)點(diǎn),他們可以通過惟一的id進(jìn)行區(qū)分
下面這張是Diff示意圖:

由此圖我們可以看出:
當(dāng)頁面的數(shù)據(jù)發(fā)生變化時(shí),Diff算法只會(huì)比較同一層級(jí)的節(jié)點(diǎn)
如果節(jié)點(diǎn)類型不同,直接干掉前面的節(jié)點(diǎn),再創(chuàng)建并插入新的節(jié)點(diǎn),不會(huì)再比較這個(gè)節(jié)點(diǎn)以后的子節(jié)點(diǎn)了。
如果節(jié)點(diǎn)類型相同:則會(huì)重新設(shè)置該節(jié)點(diǎn)的屬性,從而實(shí)現(xiàn)節(jié)點(diǎn)的更新。
當(dāng)某一層有很多相同的界定時(shí),也就是列表節(jié)點(diǎn),Diff算法的更新過程默認(rèn)情況下也是遵循以上原則。比如下面這個(gè)情況:

我們希望可以在B和C之間加一個(gè)F,Diff算法默認(rèn)執(zhí)行起來是這樣的:

既把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很沒效率?

所以我們需要使用key來給每個(gè)節(jié)點(diǎn)做一個(gè)唯一的標(biāo)識(shí),Diff算法就可以正確地識(shí)別此節(jié)點(diǎn),找到正確的位置區(qū)域插入新的節(jié)點(diǎn)
所以一句話,key的作用主要是為了高效地更新虛擬DOM,另外vue在使用相同標(biāo)簽名元素的過渡切換時(shí),也會(huì)使用到key屬性。其目的也是為了讓vue可以區(qū)分他們,否則vue只會(huì)替換其內(nèi)部屬性而不會(huì)觸發(fā)過渡效果。
深度剖析:如何實(shí)現(xiàn)一個(gè)Virtual DOM算法
所謂的Virtual DOM算法,包括幾個(gè)步驟:
1.用JavaScript對(duì)象結(jié)構(gòu)表示DOM樹的結(jié)構(gòu);然后用這個(gè)樹構(gòu)建一個(gè)真正的DOM樹,插到文檔中
2.當(dāng)狀態(tài)變更的時(shí)候,重新構(gòu)造一顆新的對(duì)象樹。然后新的樹和舊的樹進(jìn)行比較。記錄兩棵樹差異
3.把2所記錄的差異應(yīng)用到步驟1所構(gòu)建的真正的DOM樹上,視圖就更新了