目錄
前言
Vdom
(虛擬dom)憑借著出色的性能成為了目前的主流的前端框架都會(huì)選擇的渲染方案蒜哀。再加上優(yōu)秀的 diff
算法對(duì)它的一步步的優(yōu)化,使框架的價(jià)值得到了極致的體現(xiàn),幾乎成為了我們前端開(kāi)發(fā)必不可少的方案吧碾。
我們已經(jīng)知道颅围,Vue2.x 中的 Vdom
已經(jīng)相當(dāng)出色了粘我,性能非常優(yōu)秀聂薪。不過(guò)令人興奮的是瞭亮,盡管它夠快方仿,但在 Vue3 中還是對(duì) Vdom
進(jìn)行了重寫(xiě),使 Vue3 突破了 Vdom
的性能瓶頸统翩,更快仙蚜!
Vue3 如何重寫(xiě) Vdom
在開(kāi)始介紹之前,先給大家推薦一個(gè)網(wǎng)站:[https://vue-next-template-explorer.netlify.app]
這是 Vue3 官方的演示 Vdom
的示例網(wǎng)站厂汗,本篇文檔也是基于它進(jìn)行演示委粉。
1. 入門(mén)
-
當(dāng)我們創(chuàng)建一個(gè)這樣的靜態(tài) dom 元素的時(shí)候:
真實(shí)DOM -
Vue3 給我們編譯后的
Vdom
是這個(gè)樣子的:虛擬dom
看似比較復(fù)雜,實(shí)際上 _createBlock
函數(shù)中才是我們創(chuàng)建的 dom
娶桦,從它身上我們可以看出贾节,我們創(chuàng)建了一個(gè) span
元素,內(nèi)容為 “Hello World!”衷畦。這就是 Vdom
最基礎(chǔ)的形式栗涂,在這里我們并不會(huì)感覺(jué)到 Vue3 與 Vue2 有什么不同。
2. patch flag 優(yōu)化靜態(tài)樹(shù)
-
當(dāng)我們創(chuàng)建了一個(gè)動(dòng)態(tài)的 dom 元素:
真實(shí)動(dòng)態(tài)dom -
Vue3 編譯后的
Vdom
是這個(gè)樣子的:虛擬動(dòng)態(tài)dom
我們發(fā)現(xiàn)創(chuàng)建動(dòng)態(tài) dom 元素的時(shí)候祈争,Vdom
除了模擬出來(lái)了它的基本信息之外斤程,還給它加了一個(gè)標(biāo)記: 1 /* TEXT */
這個(gè)標(biāo)記就叫做 patch flag
(補(bǔ)丁標(biāo)記)
patch flag
的強(qiáng)大之處在于,當(dāng)你的 diff
算法走到 _createBlock
函數(shù)的時(shí)候铛嘱,會(huì)忽略所有的靜態(tài)節(jié)點(diǎn)暖释,只對(duì)有標(biāo)記的動(dòng)態(tài)節(jié)點(diǎn)進(jìn)行對(duì)比袭厂,而且在多層的嵌套下依然有效墨吓。
盡管 JavaScript
做 Vdom
的對(duì)比已經(jīng)非常的快球匕,但是 patch flag
的出現(xiàn)還是讓 Vue3 的 Vdom 的性能得到了很大的提升,尤其是在針對(duì)大組件的時(shí)候帖烘。
3. patch flag 優(yōu)化靜態(tài)屬性
1. 靜態(tài)綁定
-
當(dāng)我們創(chuàng)建一個(gè)有屬性的元素:
有屬性的DOM -
Vue3 編譯后的
Vdom
是這個(gè)樣子的:有屬性的Vdom讓我們觀察它的
patch flag
亮曹,發(fā)現(xiàn)并沒(méi)有對(duì) id 做特殊的標(biāo)記。是因?yàn)?dom 元素的靜態(tài)屬性在渲染的時(shí)候就已經(jīng)創(chuàng)建了秘症,并且是不會(huì)變動(dòng)的照卦,在后面進(jìn)行更新的時(shí)候,diff 算法是不會(huì)去管它的乡摹。
2. 動(dòng)態(tài)綁定
-
當(dāng)我們創(chuàng)建一個(gè)屬性是動(dòng)態(tài)綁定的元素:
動(dòng)態(tài)屬性元素 -
Vue3 編譯后的
Vdom
是這個(gè)樣子的:動(dòng)態(tài)屬性元素Vdom再觀察它的
patch flag
役耕,會(huì)發(fā)現(xiàn)變成了9 /* TEXT, PROPS */
,而且后邊多了一個(gè)數(shù)組["id"]
這里的
patch flag
中的注釋的內(nèi)容告訴我們聪廉,這一個(gè) dom 元素不止有內(nèi)容TEXT
會(huì)變化瞬痘,它的屬性PROPS
也會(huì)變化。而后邊的數(shù)組中的內(nèi)容則是有可能發(fā)生變化的屬性板熊。
看到這里框全,我們就會(huì)明白 Vue3 實(shí)際做的事情了。
Vue3 在 Vdom
的更新時(shí)干签,只會(huì)關(guān)注它有變化的部分津辩。這樣的優(yōu)化使 Vue3 既跳出了 Vdom 的性能瓶頸,又依然保留了可以手寫(xiě) render function
的靈活性容劳。相當(dāng)于 Vue3 既有 react 的靈活性喘沿,又有基于模板的性能保證〗叻罚——尤雨溪
4. 靜態(tài)提升
剛剛我們提到 Vue3 突破 Vdom
的性能瓶頸的方式是蚜印,只關(guān)注它有變化的部分。而在更新時(shí)具體是怎么做的呢娶视?
具體的做法就是 靜態(tài)樹(shù)的提升 和 靜態(tài)屬性的提升
-
我們創(chuàng)建若干的 dom 元素:
dom元素 -
靜態(tài)提升之后:
靜態(tài)提升后的dom元素我們已經(jīng)知道處理后的
Vdom
都在_createBlock
函數(shù)之中晒哄,而觀察結(jié)果我們發(fā)現(xiàn),所有的靜態(tài)元素都被放在了_createBlock
函數(shù)之外了肪获,也就是說(shuō)他們只會(huì)在頁(yè)面初始的時(shí)候被渲染一次寝凌,而在更新的時(shí)候,靜態(tài)元素是不予搭理的孝赫。這個(gè)優(yōu)化就是 Vue3 的 靜態(tài)提升
5. 事件偵聽(tīng)器緩存
了解 react 的同學(xué)都知道较木,在我們使用 react 時(shí),對(duì)其性能優(yōu)化的其中一點(diǎn)就是將偵聽(tīng)方法手動(dòng)進(jìn)行緩存青柄,避免更新組件時(shí)被多次重新創(chuàng)建伐债。而 Vue3 直接替我們做了這一點(diǎn)
-
創(chuàng)建一個(gè)帶有事件偵聽(tīng)的元素
有事件偵聽(tīng)的dom -
沒(méi)有進(jìn)行事件偵聽(tīng)器緩存的
Vdom
沒(méi)有事件偵聽(tīng)緩存的Vdom在這里的
_createBlock
函數(shù)中就是這個(gè)元素的Vdom
結(jié)構(gòu)预侯。觀察高亮的地方,發(fā)現(xiàn)onClick
函數(shù)以變量的形式存在峰锁。 -
進(jìn)行事件偵聽(tīng)器緩存后的
Vdom
有事件偵聽(tīng)緩存的Vdom觀察高亮的那一行萎馅,我們發(fā)現(xiàn)
onClick
函數(shù)的儲(chǔ)存位置變成了緩存的形式。也就是說(shuō) 當(dāng)你的頁(yè)面在不斷的更新的時(shí)候虹蒋,你的事件偵聽(tīng)器并不會(huì)重復(fù)地銷(xiāo)毀再創(chuàng)建糜芳,而是以緩存的形式存在,這使 Vue3 在性能方面又有了一個(gè)出彩的地方魄衅。另外峭竣,Vue3 在
@click
中,直接手寫(xiě)內(nèi)聯(lián)函數(shù)也會(huì)被緩存起來(lái)晃虫,這一點(diǎn)是 react 做不到的皆撩。再加上 在 Vue3 中父組件的更新并不會(huì)直接觸發(fā)子組件的更新,使得事件偵聽(tīng)器緩存在組件的層面可以提現(xiàn)出來(lái)更高的價(jià)值哲银。
其他
以后的章節(jié)
總結(jié)
Vue3 在性能優(yōu)化上的小方面扛吞,直接在編譯的時(shí)候給你做到最好,這是它最有價(jià)值的地方盘榨。想必看完這些東西喻粹,你一定更期待 Vue3 的發(fā)布了!