什么是虛擬DOM


一、前言

虛擬DOM概念隨着react的誕生而誕生,由facebook提出,其卓越的性能很快得到廣大開發者的認可;繼react之后vue2.0也在其核心引入了虛擬DOM的概念,本文將以vue2.0使用的snabbdom入手,來介紹虛擬DOM的主要實現原理。

二、虛擬DOM

在開始介紹snabbdom之前我們想來想兩個問題,

(1)什么是虛擬DOM?

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

 

 

可見左邊的DOM結構,不論是標簽名稱還是標簽的屬性或標簽的子集,都會對應在右邊的樹結構里。

(2)為什么要使用虛擬DOM?

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

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

(3)vdom如何使用?

下面我將使用snabbdom的用法介紹一下vdom的使用。

三、snabbdom

要了解snabbdom的話有必要先去github上先了解下snabbdom: https://github.com/snabbdom/snabbdom

在這里看到官方給的一個example

這里可以看到列出來的兩個主要的核心函數,即h()函數和patch()函數,我們先來看下h()函數:

h函數

 

 可以看到創建的虛擬DOM樹里面的結構在左邊的vnode里都有體現,所以現在看來我們的虛擬DOM結構樹和snabbdom中的h()函數是完全可以對應起來的,可以通過一個方法將虛擬DOM結構轉化成vnode;而上圖中newVnode則指的是虛擬DOM樹中的數據發生變化之后生成的vnode。

我們在回過頭來看patch()函數

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的對比的呢?參考以下代碼:

 1 function updateChildren(vnode, newVnode) {      // 創建對比函數
 2     var children = vnode.children || [] 3 var newChildren = newVnode.children || [] 4 5  children.forEach(function(childrenVnode, index) { 6 var newChildVnode = newChildren[index] // 首先拿到對應新的節點 7 if (childrenVnode.tag === newChildVnode.tag) { // 判斷節點是否相同 8  updateChilren(childrenVnode, newChildVnode) // 如果相同執行遞歸,深度對比節點 9 } else { 10  repleaseNode(childrenVnode, newChildVnode) // 如果不同則將舊的節點替換成新的節點 11  } 12  }) 13 } 14 15 16 function repleaseNode(vnode, newVnode) { // 節點替換函數 17 var elem = vnode.elem 18 var newEle = createElement(newVnode) 19 }

此處簡單的列舉了一下diff算法的原理,以上是最簡單的對比,更復雜的對比函數包括對節點的增刪以及其它的節點邏輯就不一一贅述了,這里最重要的一部分就是遞歸的使用,才能將vnode進行深度對比。

四、小結

虛擬DOM在目前流行的幾大框架中都作為核心的一部分使用,可見其性能的高效,本文只是簡單的通過列舉vue中使用的snabbdom庫做一個簡單的剖析,想要更深層次的理解vdom還有很長的路要走,本文如有不當之處,還勞煩路過大佬批評指出。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM