這里給大家分享我在網(wǎng)上總結(jié)出來(lái)的一些知識(shí),希望對(duì)大家有所幫助
前言
本文我們會(huì)先聊聊 DOM 的一些缺陷,然后在此基礎(chǔ)上介紹虛擬 DOM 是如何解決這些缺陷的,最后再站在雙緩存和 MVC 的視角來(lái)聊聊虛擬 DOM。理解了這些會(huì)讓你對(duì)目前的前端框架有一個(gè)更加底層的認(rèn)識(shí),這也有助于你更好地理解這些前端框架。
DOM 的缺陷
比如,我們可以調(diào)用 document.body.appendChild(node)
往 body
節(jié)點(diǎn)上添加一個(gè)元素,調(diào)用該 API 之后會(huì)引發(fā)一系列的連鎖反應(yīng)。首先渲染引擎會(huì)將 node
節(jié)點(diǎn)添加到 body
節(jié)點(diǎn)之上,然后觸發(fā)樣式計(jì)算、布局、繪制、柵格化、合成等任務(wù),我們把這一過(guò)程稱(chēng)為 重排。除了重排之外,還有可能引起重繪或者合成操作,形象地理解就是“牽一發(fā)而動(dòng)全身”。另外,對(duì)于 DOM 的不當(dāng)操作還有可能引發(fā)強(qiáng)制同步布局和布局抖動(dòng)的問(wèn)題,這些操作都會(huì)大大降低渲染效率。因此,對(duì)于 DOM 的操作時(shí)我們需要非常謹(jǐn)慎。
對(duì)于一些復(fù)雜的頁(yè)面或者目前使用非常多的單頁(yè)應(yīng)用來(lái)說(shuō),其 DOM 結(jié)構(gòu)是非常復(fù)雜的,而且還需要不斷地去修改 DOM 樹(shù),每次操作 DOM 渲染引擎都需要進(jìn)行重排、重繪或者合成等操作,因?yàn)?DOM 結(jié)構(gòu)復(fù)雜,所生成的頁(yè)面結(jié)構(gòu)也會(huì)很復(fù)雜,對(duì)于這些復(fù)雜的頁(yè)面,執(zhí)行一次重排或者重繪操作都是非常耗時(shí)的,這就給我們帶來(lái)了真正的性能問(wèn)題。所以我們需要有一種方式來(lái)減少 JavaScript 對(duì) DOM 的操作,這時(shí)候虛擬 DOM 就上場(chǎng)了。
什么是虛擬 DOM?
在談?wù)撌裁词翘摂M DOM 之前,我們先來(lái)看看虛擬 DOM 到底要解決哪些事情。
- 將頁(yè)面改變的內(nèi)容應(yīng)用到虛擬 DOM 上,而不是直接應(yīng)用到 DOM 上。
- 變化被應(yīng)用到虛擬 DOM 上時(shí),虛擬 DOM 并不急著去渲染頁(yè)面,而僅僅是調(diào)整虛擬 DOM 的內(nèi)部狀態(tài),這樣操作虛擬 DOM 的代價(jià)就變得非常輕了。
- 在虛擬 DOM 收集到足夠的改變時(shí),再把這些變化一次性應(yīng)用到真實(shí)的 DOM 上。
基于以上三點(diǎn),我們?cè)賮?lái)看看什么是虛擬 DOM。為了直觀理解,你可以參考下圖:
該圖是結(jié)合 React 流程畫(huà)的一張?zhí)摂M DOM 執(zhí)行流程圖,下面我們就結(jié)合這張圖來(lái)分析下虛擬 DOM 到底怎么運(yùn)行的。
- 創(chuàng)建階段。首先依據(jù) JSX 和基礎(chǔ)數(shù)據(jù)創(chuàng)建出來(lái)虛擬 DOM,它反映了真實(shí)的 DOM 樹(shù)的結(jié)構(gòu)。然后由虛擬 DOM 樹(shù)創(chuàng)建出真實(shí) DOM 樹(shù),真實(shí)的 DOM 樹(shù)生成完后,再觸發(fā)渲染流水線往屏幕輸出頁(yè)面。
- 更新階段。如果數(shù)據(jù)發(fā)生了改變,那么就需要根據(jù)新的數(shù)據(jù)創(chuàng)建一個(gè)新的虛擬 DOM 樹(shù);然后 React 比較兩個(gè)樹(shù),找出變化的地方,并把變化的地方一次性更新到真實(shí)的 DOM 樹(shù)上;最后渲染引擎更新渲染流水線,并生成新的頁(yè)面。
既然聊到虛擬 DOM 的更新,那我們就不得不聊聊最新的 React Fiber 更新機(jī)制了。最開(kāi)始的時(shí)候,比較兩個(gè)虛擬 DOM 的過(guò)程是在一個(gè)遞歸函數(shù)里執(zhí)行的,其核心算法是 reconciliation。通常情況下,這個(gè)比較過(guò)程執(zhí)行得很快,不過(guò)當(dāng)虛擬 DOM 比較復(fù)雜的時(shí)候,執(zhí)行比較函數(shù)就有可能占據(jù)主線程比較久的時(shí)間,這樣就會(huì)導(dǎo)致其他任務(wù)的等待,造成頁(yè)面卡頓。
為了解決這個(gè)問(wèn)題,React 團(tuán)隊(duì)重寫(xiě)了 reconciliation 算法,新的算法稱(chēng)為 Fiber reconciler,所謂的 Fiber reconciler,就是在執(zhí)行算法的過(guò)程中出讓主線程,這樣就解決了之前執(zhí)行函數(shù)占用時(shí)間過(guò)久的問(wèn)題。至于具體的實(shí)現(xiàn)過(guò)程在這里就不詳細(xì)分析了,如果感興趣的話,你可以自行查閱相關(guān)資料進(jìn)行學(xué)習(xí)。
了解完虛擬 DOM 的大致執(zhí)行流程,你應(yīng)該也就知道為何需要虛擬 DOM 了。不過(guò)以上都從單純的技術(shù)視角來(lái)分析虛擬 DOM 的,那接下來(lái)我們?cè)購(gòu)碾p緩存和 MVC 模型這兩個(gè)視角來(lái)聊聊虛擬 DOM。
雙緩存
使用雙緩存,可以讓你先將計(jì)算的中間結(jié)果存放在另一個(gè)緩沖區(qū)中,等全部的計(jì)算結(jié)束,該緩沖區(qū)已經(jīng)存儲(chǔ)了完整的圖形之后,再將該緩沖區(qū)的圖形數(shù)據(jù)一次性復(fù)制到顯示緩沖區(qū),這樣就使得整個(gè)圖像的輸出非常穩(wěn)定。
在這里,你可以把虛擬 DOM 看成是 DOM 的一個(gè) buffer,和圖形顯示一樣,它會(huì)在完成一次完整的操作之后,再把結(jié)果應(yīng)用到 DOM 上,這樣就能減少一些不必要的更新,同時(shí)還能保證 DOM 的穩(wěn)定輸出。
MVC 模式
接下來(lái)我們?cè)賮?lái)看看虛擬 DOM 在 MVC 模式中所扮演的角色。
在各大設(shè)計(jì)模式當(dāng)中,MVC 是一個(gè)非常重要且應(yīng)用廣泛的模式,因?yàn)樗軐?shù)據(jù)和視圖進(jìn)行分離,在涉及到一些復(fù)雜的項(xiàng)目時(shí),能夠大大減輕項(xiàng)目的耦合度,使得程序易于維護(hù)。關(guān)于 MVC 的基礎(chǔ)結(jié)構(gòu),你可以先參考下圖:
?
通過(guò)上圖可以發(fā)現(xiàn),MVC 的整體結(jié)構(gòu)比較簡(jiǎn)單,由模型、視圖和控制器組成,其核心思想就是將數(shù)據(jù)和視圖分離,也就是說(shuō)視圖和模型之間是不允許直接通信的,它們之間的通信是通過(guò)控制器來(lái)完成的。
比如在分析 React 項(xiàng)目時(shí),我們可以把 React 的部分看成是一個(gè) MVC 中的視圖,在項(xiàng)目中結(jié)合 Redux 就可以構(gòu)建一個(gè) MVC 的模型結(jié)構(gòu),如下圖所示:
在該圖中,我們可以把虛擬 DOM 看成是 MVC 的視圖部分,其控制器和模型都是由 Redux 提供的。其具體實(shí)現(xiàn)過(guò)程如下:
- 圖中的控制器是用來(lái)監(jiān)控 DOM 的變化,一旦 DOM 發(fā)生變化,控制器便會(huì)通知模型,讓其更新數(shù)據(jù)。
- 模型數(shù)據(jù)更新好之后,控制器會(huì)通知視圖,告訴它模型的數(shù)據(jù)發(fā)生了變化。
- 視圖接收到更新消息之后,會(huì)根據(jù)模型所提供的數(shù)據(jù)來(lái)生成新的虛擬 DOM。
- 新的虛擬 DOM 生成好之后,就需要與之前的虛擬 DOM 進(jìn)行比較,找出變化的節(jié)點(diǎn)。
- 比較出變化的節(jié)點(diǎn)之后,React 將變化的虛擬節(jié)點(diǎn)應(yīng)用到 DOM 上,這樣就會(huì)觸發(fā) DOM 節(jié)點(diǎn)的更新。
- DOM 節(jié)點(diǎn)的變化又會(huì)觸發(fā)后續(xù)一系列渲染流水線的變化,從而實(shí)現(xiàn)頁(yè)面的更新。
在實(shí)際工程項(xiàng)目中,你需要學(xué)會(huì)分析出各個(gè)模塊,并梳理出它們之間的通信關(guān)系,這樣對(duì)于任何框架你都能輕松上手了。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-607552.html
本文轉(zhuǎn)載于:
https://juejin.cn/post/7226971906652979255
如果對(duì)您有所幫助,歡迎您點(diǎn)個(gè)關(guān)注,我會(huì)定時(shí)更新技術(shù)文檔,大家一起討論學(xué)習(xí),一起進(jìn)步。
?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-607552.html
到了這里,關(guān)于記錄--虛擬 DOM 和實(shí)際 DOM 有何不同?的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!