為什麼Vue.js中要採用虛擬DOM

語言: CN / TW / HK

Vue.js中採用虛擬DOM的前因後果

引言

在我上一篇筆記Vue.js檢視層框架設計-命令式與宣告式中談到Vue.js在檢視層框架設計中採用的是命令式內部實現+宣告式外部暴露的構建方案,那麼就存在一個擺在明面上的問題:選擇了儘可能地把宣告式暴露給使用者,那麼對效能必定會有所影響,即宣告式程式碼的更新消耗 = 找出差異的效能消耗 + 直接修改的效能消耗(命令式)。到此,如何儘可能地降低找出差異的效能消耗成為迫切需要解決的問題,Vue.js設計團隊給出的方案就是虛擬DOM

什麼是虛擬DOM

在前端領域,DOM指的是文件物件模型,是HMTL和XML文件的程式設計介面,提供了一種對文件的結構化表述。而虛擬DOM簡言而之,就是用JavaScript仿照DOM結構實現的一種樹形結構物件,如Vue.js官方文件中寫明的渲染函式h()就實現了建立虛擬DOM節點的功能,如下:

QQ截圖20220223200843.jpg

虛擬DOM與innerHTML的效能比較

建立頁面時的效能比較

虛擬DOM

虛擬DOM在建立頁面的過程中分為兩步:

mermaid graph TD 建立JavaScript物件 --> 遞迴遍歷虛擬DOM樹並建立真實DOM

用一個公式來表示使用虛擬DOM建立頁面的效能:建立JavaScript物件的計算量 + 建立真實DOM的計算量

innerHTML

使用innerHTML建立頁面的程式碼如下:

carbon (9).png

看起來簡單吧?可是這段程式碼的內部實現可沒看起來的這麼簡單。為了渲染出頁面,首先要把字串解析成DOM樹,這可是一個DOM層面的計算操作,比純JavaScript層面的操作要慢上許多。

用一個公式來表示通過innerHTML建立頁面的效能:HTML字串拼接的計算量 + innerHTML的DOM計算量

圖表對比

| | 虛擬DOM | innerHTML | | --- | --- | --- | | 純JavaScript運算 | 建立JavaScript物件(VNode) | 渲染HTML字串 | | DOM運算 | 新建所有DOM元素 | 新建所有DOM元素 |

可見,從巨集觀的角度上看,在建立頁面時各方法的效能差別不大

更新頁面時的效能比較

更新頁面是在建立頁面的基礎上進行選擇性的替換

虛擬DOM

  • 重新建立JavaScript物件(虛擬DOM樹)
  • 呼叫Diff演算法找到變化的元素並更換

innerHTML

  • 重新構建HTML字串
  • 重新設定DOM元素的innerHTML屬性

圖表對比

| | 虛擬DOM | innerHTML | | --- | --- | --- | | 純JavaScript運算 | 建立新的JavaScript物件+Diff | 渲染HTML字串 | | DOM運算 | 必要的DOM更新 | 銷燬所有舊DOM並新建所有新DOM | | 效能因素 | 與資料的變化量有關 | 與模板大小有關 |

對於虛擬DOM來說,只需要更新變化的元素,而對於使用innerHTML來說,需要刪除所有舊DOM並新建所有新DOM,而且效能上的消耗隨模板的增大而越來越大,這時,虛擬DOM的優勢就體現出來了。

總結

Vue.js採用虛擬DOM是在各方面平衡的結果,既降低了使用者的學習成本與使用成本(寫宣告式程式碼),還保證了應用程式的效能下限,讓應用程式的效能不至於太差,甚至儘可能地逼近命令式程式碼的效能

各方案效能由高到低如下: - 原生JavaScript(心智負擔大、可維護性差、效能高) - 虛擬DOM(心智負擔小、可維護性強、效能不錯) - innerHTML模板(心智負擔中等、效能差)

宣告

  • 本文屬於讀書筆記一類,是作者在拜讀 霍春陽 大佬的新作《Vue.js設計與實現》途中,以書中內容為藍本,輔以個人微末的道行“填寫”完成
  • 歡迎大佬斧正
  • 日更

參考資料