虛擬 DOM 是什么
- 虛擬 DOM 是 JS 對象
- 虛擬 DOM 是對真是 DOM 的描述
虛擬 DOM 的本質是 JS 和 DOM 之間的一個映射緩存,它形態上表現為一個能夠描述 DOM 結構及其屬性信息的 JS 對象。
React 中的虛擬 DOM 是怎么工作的
-
掛載階段
: React 將結合 JSX 描述,構建出虛擬 DOM 數,然后通過 ReactDOM.render 實現虛擬 DOM 到真是 DOM 的映射。 -
更新階段
:頁面的變化在作用于真實 DOM 之前,會先作用于虛擬 DOM,虛擬 DOM 將在 JS 層借助算法先對比出具體有哪些真實 DOM 需要被改變,然后將這些改變作用于真實 DOM。
前端 DOM 操作解決方案的發展史
- 原生 JS 操作的時期
- 在前端這個工種的萌芽階段,前端頁面“展示”的屬性遠遠強于其“交互”的屬性,這就導致 JS 的定位只能是“輔助”:在很長一段時間里,前端工程師們會花費大量的時間去實現靜態的 DOM,待一切結束后,再補充少量 JS,實現一些類似于拖拽、隱藏、幻燈片之類的“特效”。
- 解放生產力的先導階段 jQuery 時期
- 隨著開始最求更加豐富的用戶體驗,前端交互帶來大量的 DOM 操作,人們發現 JS 原生提供的 DOM API,太難用了,為了實現高效的開發,jQuery 就誕生了,它將 DOM API 封裝為了相對簡單和優雅的形式,同時一口氣做掉了跨瀏覽器的兼容工作,并且提供了鏈式 API 調用、插件擴展等一系列能力用于進一步解放生產力。
- jQuery 使 DOM 操作變得簡單、快速,并且始終確保其形式穩定、可用性穩定。
- 模板引擎的方案
- jQuery 幫助我們能夠以更舒服的姿勢操作 DOM,但它并不能從根本上解決 DOM 操作量過大情況下前端側的壓力。
- 什么是模板引擎,大概內容數據如下:
const data = [
{
name: 'achang',
age: 18
},
...
]
- 使用模板
<table>
{% data.forEach(function(p){ %}
<tr>
<td>{% p.name %}</td>
<td>{% p.age %}</td>
</tr>
{% }); %}
</table>
- 其實就是把 JS 和 HTML 結合在一起的一種規則。把數據源讀進去,塞到預置好的 HTML 模板里,然后把兩者融合在一起,吐出一段目標字符串。這段字符串的內容,其實就是一份標準的、可用于渲染的 HTML 代碼,它將對應一個 DOM 元素。最后,將這個 DOM 元素掛載到頁面中去。
- 模板引擎一會會做幾件事:
- 讀取 HTML 模板并解析它,分離其中的 JS 信息
- 將解析出的內容拼接成字符串,動態生成 JS 代碼;
- 運行動態生成的 JS 代碼,返回目標 HTML
- 將 HTML 賦值給 innerHTML,觸發渲染,生成真實 DOM。
但是它在性能上的表現并不盡如人意:由于不夠 “智能”,它更新 DOM 的方式是將已經渲染出 DOM 整體注銷后再整體重渲染,并且不存在更新緩沖這一說。在 DOM 操作頻繁的場景下,模板引擎可能會直接導致頁面卡死。
- 虛擬 DOM
- 利用
“數據驅動視圖”
- 虛擬 DOM 的好處是:當 DOM 操作(渲染更新)比較頻繁時,它利用 diff 算法先將前后兩次的虛擬 DOM 樹進行對比,定位出具體需要更新的部分,生成一個“補丁集”,最后只把“補丁”打在需要更新的那部分真實 DOM 上,實現精準的
“差量更新”
。
為什么虛擬 DOM 的價值不在性能
- 虛擬 DOM 并不一定會帶來更好的性能,React 官方也從來沒有把虛擬 DOM 作為性能層面的賣點對外輸出過。
- 虛擬 DOM 的優越之處在于,它能夠在提供
更爽、更高效的研發模式(也就是函數式的 UI 編程方式)的同時,仍然保持一個還不錯的性能
。
虛擬 DOM 對比模板引擎
-
模板引擎是:
- 直接生成新的 DOM
- 替換舊的 DOM
-
虛擬 DOM 是:
- 先構建新的虛擬 DOM 樹
- 使用 diff 對比新舊兩棵樹的差異
- 更新差異 DOM
模板1 和 虛擬1,2 都是 JS 范疇內,放到一起看,動態生成 HTML 字符串性能消耗有限,而“虛擬DOM”構建和 diff 算法邏輯規則相對復雜,避免不了涉及到遞歸,遍歷等耗時操作,因為這個JS層面,虛擬DOM并不比模板引擎快。
對比 模板2 和虛擬3 都是屬于 DOM 范疇,
模板渲染是全量更新,而虛擬 DOM 是差量更新
。 乍一看可能差量更新高效,可需要考慮這種情況,數據內容變化非常大(或者說整個發生了改變),促使差量更新計算出來的結果和全量更新極為接近,而在情況下,虛擬 DOM 還有大量的 JS 開銷時間,此時會有一個現象就是二者可能難分伯仲
,但是如果 虛擬 DOM 在 DOM 操作上比模板引擎快,那么他們的系性能差距可是巨大的,虛擬 DOM 完勝模板引擎。因為虛擬 DOM 的劣勢主要在于 JS 計算的耗時,而 DOM 操作的能耗和 JS 計算的能耗根本不在一個量級
,極少量的 DOM 操作耗費的性能足以支撐大量的 JS 計算
。
那么虛擬 DOM 的價值到底是什么呢?
- 虛擬 DOM 解決了一下兩個問題
-
研發體驗、研發效率
的問題:
- DOM 操作模式的每一次革新,背后都是前端對效率和體驗的進一步追求。虛擬 DOM 的出現,
為數據驅動視圖這一思想提供了高度可用的載體,使得前端開發能夠基于函數式 UI 的編程方式實現高效的聲明式編程(JSX便是其中一個品類)
。
-
跨平臺的問題
(同一套虛擬 DOM 可以在不同的平臺渲染)
- 虛擬 DOM 是對真實渲染內容的一層抽象。