1越除、虛擬DOM
虛擬DOM藤乙,也就是虛擬節(jié)點(diǎn),本質(zhì)上是使用js對(duì)象來(lái)模擬真實(shí)DOM中存在的節(jié)點(diǎn)阶界,這個(gè)對(duì)象具有真實(shí)DOM的特性虹钮。
如:
真實(shí)dom:
<div id="app">
<h1>dom元素<h1>
</div>
虛擬dom:
{
tag:'div',
attrs:{
// 表示該節(jié)點(diǎn)的屬性
id:'app'
},
children:[
{
tag:'h1',
text:'dom元素'
}
]
}
1.1、使用虛擬DOM的原因
不斷的修改真實(shí)的DOM會(huì)引發(fā)回流和重繪膘融,大大降低了頁(yè)面的渲染能力芙粱,而虛擬DOM的產(chǎn)生則是減少了頻繁操作DOM而帶來(lái)的一系列性能問(wèn)題。
1.2氧映、使用虛擬DOM真正的意義
虛擬DOM的頻繁改變會(huì)產(chǎn)生一系列性能問(wèn)題春畔,而使用虛擬DOM替代真實(shí)DOM,最大的優(yōu)勢(shì)在于不斷的去修改虛擬DOM后岛都,才會(huì)一次性的與真實(shí)DOM的差異性做對(duì)比律姨,然后只會(huì)去修改真實(shí)的DOM一次。而這種差異性對(duì)比臼疫,也就是diff算法择份。
2、diff算法
當(dāng)虛擬DOM的某個(gè)節(jié)點(diǎn)發(fā)生了變化烫堤,會(huì)生成一個(gè)新的VNode荣赶,然后通過(guò)新的VNode與之前的舊的VNode進(jìn)行對(duì)比凤价,把不同的地方修改在真實(shí)的DOM上,在將舊的VNode更新節(jié)點(diǎn)的值讯壶。
diff過(guò)程的核心就是去使用patch函數(shù)料仗,對(duì)比新老節(jié)點(diǎn),然后修改真實(shí)DOM伏蚊。
圖片是從其他地方引入的立轧。
diff過(guò)程:
-
1、按照樹(shù)的層級(jí)劃分
image.png
由于同key值比較躏吊,也就是一些列表的for循環(huán)中需要加入key唯一鍵的原因氛改,如果不加入key值,那么在更新DOM樹(shù)的時(shí)候比伏,它就不能根據(jù)你的需求去比較胜卤,這也就會(huì)導(dǎo)致最后多出個(gè)節(jié)點(diǎn)出來(lái)。 -
2赁项、同key值比較
image.png
diff算法的特性
當(dāng)最外層的根節(jié)點(diǎn)發(fā)生改變葛躏,那么diff算法默認(rèn)內(nèi)部發(fā)生了翻天覆地的變化,因此悠菜,diff算法更新節(jié)點(diǎn)的發(fā)生是采用react的策略:刪除舊的節(jié)點(diǎn)舰攒,再去創(chuàng)建一個(gè)新的節(jié)點(diǎn)。
如:
舊的虛擬DOM:
{
tag:'div',
attrs:{
// 表示該節(jié)點(diǎn)的屬性
id:'app'
},
children:[
{
tag:'h1',
text:'dom元素'
}
]
}
新的虛擬DOM:
{
tag:'p',
attrs:{
// 表示該節(jié)點(diǎn)的屬性
id:'app'
},
children:[
{
tag:'h1',
text:'dom元素'
}
]
}
盡管內(nèi)部的數(shù)據(jù)還是一樣的悔醋,但是此時(shí)diff并不會(huì)去進(jìn)行差異性比較摩窃,而是將舊的div節(jié)點(diǎn)直接刪除,直接新建一個(gè)p節(jié)點(diǎn)芬骄。
證明理由:
在Vue的transition過(guò)渡動(dòng)畫(huà)中猾愿,會(huì)出現(xiàn)這種情況,當(dāng)是復(fù)用的組件使用過(guò)渡動(dòng)畫(huà)時(shí)账阻,是不會(huì)產(chǎn)生過(guò)渡效果的蒂秘,而不同的組件使用動(dòng)畫(huà)時(shí),是能使用過(guò)渡效果的淘太,產(chǎn)生這種問(wèn)題的原因就是上述所說(shuō)的材彪,當(dāng)組件復(fù)用時(shí),沒(méi)有創(chuàng)建銷毀的過(guò)程琴儿,只是根據(jù)diff去進(jìn)行差異性比較段化。