虛擬DOM的實現原理和優劣對比

虛擬DOM的實現原理和優劣對比


Web界面由DOM樹(樹的意思是數據結構)來構建,當其中一部分發生變化時,其實就是對應某個DOM節點發生了變化。

虛擬DOM就是爲了解決瀏覽器性能問題而被設計出來的。如前,若一次操作中有10次更新DOM的動作,虛擬DOM不會立即操作DOM,而是將這10次更新的diff內容保存到本地一個JS對象中,最終將這個JS對象一次性attch到DOM樹上,再進行後續操作,避免大量無謂的計算量。所以,用JS對象模擬DOM節點的好處是,頁面的更新可以先全部反映在JS對象(虛擬DOM)上,操作內存中的JS對象的速度顯然要更快,等更新完成後,再將最終的JS對象映射成真實的DOM,交由瀏覽器去繪製。

虛擬DOM概念隨着react的誕生而誕生,由facebook提出,其卓越的性能很快得到廣大開發者的認可;繼react之後vue2.0也在其核心引入了虛擬DOM的概念;

本章節,我們來逐步學習虛擬DOM的原理及其性能的優劣知識點梳理:

什麼是虛擬DOM ?

虛擬dom可以看作是一個使用javascript模擬了DOM結構的樹形結構,這個樹結構包含整個DOM結構的信息,如下圖所示:

在這裏插入圖片描述

爲什麼使用虛擬DOM ?

之前使用原生js或者jquery寫頁面的時候會發現操作DOM是一件非常麻煩的一件事情,往往是DOM標籤和js邏輯同時寫在js文件裏,數據交互時不時還要寫很多的input隱藏域,如果沒有好的代碼規範的話會顯得代碼非常冗餘混亂,耦合性高並且難以維護。

另外一方面在瀏覽器裏一遍又一遍的渲染DOM是非常非常消耗性能的,常常會出現頁面卡死的情況;所以儘量減少對DOM的操作成爲了優化前端性能的必要手段,vdom就是將DOM的對比放在了js層,通過對比不同之處來選擇新渲染DOM節點,從而提高渲染效率。

patch函數

patch函數的執行分爲兩個階段,兩次傳遞的參數都是兩個

第一階段爲虛擬dom的第一次渲染,傳遞的兩個參數分別是放真實DOM的container和生成的vnode,此時patch函數的作用是用來將初次生成的真實DOM結構掛載到指定的container上面。

第二階段傳遞的兩個參數分別爲vnode和newVnode,此時patch函數的作用是使用diff算法對比兩個參數的差異,進而更新參數變化的DOM節點;

可以發發現h函數和patch函數在cnabbdom中實現vdom到真實DOM的轉化起到了至關重要的作用,那麼還有一個很重要的環節,patch函數中是怎麼樣實現對比兩個vnode從而實現對真實DOM的更新的呢,這裏還要提一下snabbdom的另外一個核心算法,即diff算法。

diff算法

其實在我們日常開發中我們都在接觸類似與diff算法的一些軟件,比如svn可以看到當前代碼和svn服務器上代碼的不同之處,再如Beyond Compare這款軟件也可以爲我們指出兩個對比文件的不同之處

但是此處是如何實現對vnode的對比的呢?參考以下代碼:

let children = vnode.children || []         
let newChildren = newVnode.children || []

children.forEach(function(childrenVnode, index) {
    var newChildVnode = newChildren[index]  // 首先拿到對應新的節點
    if (childrenVnode.tag === newChildVnode.tag) {    // 判斷節點是否相同
        updateChilren(childrenVnode, newChildVnode)   // 如果相同執行遞歸,深度對比節點
    } else {
        repleaseNode(childrenVnode, newChildVnode)    // 如果不同則將舊的節點替換成新的節點
    }
})
}


function repleaseNode(vnode, newVnode) {    // 節點替換函數
    let elem = vnode.elem
    let newEle = createElement(newVnode)
}

總結

  • 虛擬DOM的實現原理:
    • 虛擬DOM本質上是JavaScript對象,是對真實DOM的抽象
    • 狀態變更時,記錄新樹和舊樹的差異
    • 最後把差異更新到真正的dom中
  • 虛擬DOM的優劣如何?
    • 優點:
    • 保證性能下限: 虛擬DOM可以經過diff找出最小差異,然後批量進行patch,這種操作雖然比不上手動優化,但是比起粗暴的DOM操作性能要好很多,因此虛擬DOM可以保證性能下限
    • 無需手動操作DOM: 虛擬DOM的diff和patch都是在一次更新中自動進行的,我們無需手動操作DOM,極大提高開發效率
    • 跨平臺: 虛擬DOM本質上是JavaScript對象,而DOM與平臺強相關,相比之下虛擬DOM可以進行更方便地跨平臺操作,例如服務器渲染、移動端開發等等
    • 缺點:
    • 無法進行極致優化: 在一些性能要求極高的應用中虛擬DOM無法進行鍼對性的極致優化,比如VScode採用直接手動操作DOM的方式進行極端的性能優化
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章