iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 20
1
Modern Web

前端開發 30 個問題系列 第 20

Virtual DOM

前言
2020 秋天,我將用 30 天的時間,來嘗試回答和網路前端開發相關的 30 個問題。30 天無法一網打盡浩瀚的前端知識,有些問題可能對有些讀者來說相對簡單,不過期待這趟旅程,能幫助自己、也幫助讀者打開不同的知識大門。有興趣的話,跟著我一起探索吧!


source

DOM

在前幾天的文章當中有提到,當瀏覽器讀取了 HTML 文件之後,會將 HTML 轉換成 DOM (Document Object Model)。DOM 是瀏覽器所產生出來的資料結構,一方面表現出 HTML 的內容與架構,另一方面讓開發者有機會使用 JavaScript 透過 DOM 來操作頁面。

不過透過 DOM API 來大量操作操作網頁,本身有幾個問題,一個是要在 DOM 當中同時處理資料、畫面變動、掛載或卸載監聽器,其實是相對麻煩的一件事情,而且程式碼難以維護。另一方面,當 DOM 被改變的時候,會引發許多 Reflow 和 repaint 的過程,會有效能上的顧慮。

為了解決這些問題,不同的前端框架因此誕生。在前端框架不僅僅大幅改變開發方式,也引入了不同的實作方法,來提升應用程式的效率,其中有一個重要的 feature,那就是 Virtual DOM。

Virtual DOM

Virtual DOM,中文翻譯叫做虛擬 DOM,顧名思義,他不是一個真正的 DOM。DOM 是由瀏覽器所產生,並存在在瀏覽器當中的資料結構,而 Virtual DOM 本身是一個 JavaScript 的物件,存在在 memory 當中。

為了避免每次互動引發整個 DOM 的改變,進而產生不必要的 reflow 或 repaint,前端框架在設計與實作上,會先將原本的 DOM 結構複製一份出來,但不會完整複製 DOM 當中的所有資訊,只會複製跟畫面渲染高度相關的資訊,譬如 tag (HTML tag)、props (tag 當中的資訊)與 children (子結點資訊) 等,利用 JavaScrip 物件的資料結構來儲存。

每當有事件產生,或是資料變動的時候,前端框架會先建立一個新的 virtual DOM,接著,計算出新舊 virtual DOM 之間的差別,最後才會操作真正的 DOM,並僅僅操作有變動的部分,藉此避免不必要的 reflow 或 repaint 以提升效能。

不過這裡我們也會發現,操作 virtual DOM 應為會帶來另外一個效能上的負擔,因為在實際改變 DOM 之前,會經歷建立 virtual DOM、計算差異、實際操作 DOM 的過程。只不過,操作 virtual DOM 實際上就是在操作純 JavaScript,因此在大部分的情況下,會比不夠過 virtual DOM 直接操作真正的 DOM 還要來得快許多。

Diffing

不過,前端框架是如何「計算」出差異,並降低 DOM 當中需要修改的規模呢?

若以 React 為例,要遍歷整個 virtual DOM tree 並計算出差異,會需要 O(n^3) 的時間複雜度,因此 React 做了兩個假設:

  • 兩個不同類型的 HTML element 會產生不同的 tree
  • 開發者可以透過 "key" 的標記,來判斷畫面有無需要更動

因此當 React 在遍歷 virtual DOM tree 的時候,如果發現 element 類型 (tag) 不同的話,就會把該 element 以下的整個子 tree 砍掉重練,就不需要花時間再往下遍歷了。當然若遇到同樣類型的 element,就會實際去檢查當中的屬性與資料,並繼續往下(子結點)遍歷。

另一方面,透過 "key" 的標記,可以知道哪些 elements 是原本就存在在舊 virtual DOM tree 之中,因此如果只是在同一層的位置改變,就不需要重新計算修改,藉此提升整體效能。

關於 Diffing 演算法的細節,就不在這裡深入探究,有興趣的話可以參考Reconciliation虛擬 DOM 及 diff 算法 等文章。

End

前端框架不僅僅帶來開發上的便利性,背後更帶來更多觀念、架構、實作方法上的演進。多瞭解工具或框架的前世今生,以及它所要解決的問題,在開發時就會更為踏實,並發揮該工具或框架的最大價值!

Ref


TD
Be curious as astronomer, think as physicist, hack as engineer, fight as baseball player

More about me

"Life is like riding a bicycle. To keep your balance, you must keep moving."


上一篇
How browser works (6) - Painting
下一篇
HTTP, HTTPS, HTTP2
系列文
前端開發 30 個問題31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
swingcloud
iT邦新手 5 級 ‧ 2020-10-03 22:48:30

有 Virtual DOM 呀!

我要留言

立即登入留言