Virtual DOM 基本概念

yu.chiang
3 min readAug 7, 2017

--

在有 js 之前,我們在上網的時候,只會從 server 端拿到一份 html 檔案在瀏覽器做渲染,並不會與頁面有什麼互動。若有從 server 端拿資料是由 server 重新給 client 端一份新的 html,而這樣的重新渲染會使畫面閃爍,造成使用者體驗不佳。

在有 js 之後,我們除了可以即時的新增刪減畫面中的某個區塊,或是藉由 api 來取得畫面中的一些資訊,都不會造成畫面的閃爍。雖然可以自由操作畫面中的 dom 很方便,但若程式的任何地方都可操作 dom,將會使程式的追蹤較為困難。且操作 dom 是耗效能的,隨著應用越來越多且複雜,我們不能每次一有 dom 的變更就去操作 dom,這時候就需要一個方法來專門做 dom 的處理。

基本概念

virtual dom 是一個概念,它以物件型態記錄了真實在頁面上產生的 dom,假若我今天有一個 dom 的結構如下:

則這個 dom 會以下列的格式儲存起來。

其中主要有三個主要的 key 值:

  1. type 記錄 dom 的 tag name。
  2. props 記錄 dom 的屬性值。
  3. children 記錄這個 dom 所包含的子元件。

大部份的 virtual dom 都是以這樣的結構在建立,當然也不一定要完全照這樣的格式來做。

每當畫面有變更的時候,不直接去改動現有畫面上的 dom,而是去建立一個新的物件,然後再根據這個物件來建立真正的畫面。

實作

建立畫面的 function 如下:

  1. 當 children 是文字而不是物件時,表示到節點最底層了。
  2. 檢查 dom 有沒有要建立屬性,有的話為 dom 加入屬性。
  3. children 也根據這個 function 來建立節點,做 recursive。

搭配使用

但單純只使用 virtual dom 的好處也不多,因為在建立畫面的時候,這種作法會在每一次畫面有更新時,都會根據新的物件來重新建立一個新的畫面,就算只做些微的改動也會做一次重新渲染,這在頁面複雜的時候是浪費效能的。

所以基本上 github 上關於 virtual dom 套件都會附一個 diff 演算法來搭配使用,讓舊的 virtual dom 與新的 virtual dom 做比對,然後只去更新有差異的部分,減少渲染的數量來達到效能的提升。

像最近 react v16 中的 fiber 就是為了優化 dom 渲染在畫面上所出的演算法,而 virtual dom 的架構上還是沒什麼差別,所以要搭配演算法才能最大化 virtual dom 所帶來的效益。

參考:

How to write your own Virtual DOM

The Real Benefits of the Virtual DOM in React.js

--

--