# DOM

# 簡介

DOM (document object model,文件物件模型) 由 W3C (world wide web consortium) 定義,DOM 將 HTML 內的所有 element 定義成物件,並以樹狀結構表示。

DOM 樹狀結構
DOM 樹狀結構 source

# 結構

DOM 的節點大致分為四類:

  • Document: HTML 文件本身,也就是 root node。
  • Element: 文件裡的標籤,如 <head><body><div> 等。
  • Text: 被 element 包起來的文字。
  • Attribute: element 內的屬性。

將上圖的樹狀結構轉回 HTML 後如下:

<html>
    <head>
        <title>My title</title>
    </head>
    <body>
        <a href="url">My link</a>
        <h1>My header</h1>
    </body>
</html>

# Reflow & Repaint

瀏覽器在呈現出畫面之前,會先解析 HTML 與 CSS 檔並產生 render tree,而 reflow 這個步驟會遍歷 render tree 並計算所有 element 的位置、大小及其他屬性,會消耗大量效能。Repaint 步驟則是將 reflow 計算好的結果輸出到螢幕上,任何可見元素的更改都需要 repaint。

可以發現影響效能的關鍵在於 reflow,因此框架的效能優化主要在於減少 reflow 的次數及範圍。

# 沒有框架的日子

隨著專案規模逐漸增大,程式複雜度不斷上升,直接操作 DOM 的缺點也就逐漸浮出檯面:

# 難以維護

HTML、CSS、JavaScript 無法維持原先的各司其職,因為需要透過 JavaScript 處理互動內容,勢必要將結構、樣式寫到 JavaScript 的部份中,也就因此造成架構耦合度提高,程式碼管理困難。

# 效能低落

當 DOM 被改變,勢必要觸發整個 Reflow & Repaint 的流程,頻繁的改動觸發重複渲染,便會讓頁面效能被消耗殆盡。

# 框架的功能

# 資料與 UI 分離

資料不必寫死在結構裡,可以根據資料變化而改變輸出內容。

# 模組化的 UI

一個網站總是會有一些重複出現的元素,例如按鈕、輸入表單、表格、對話框等等,而在現代框架的概念中,我們會把這些重複出現的元素稱為 組件(Components),每個組件內包含了組件自己需要用的結構、樣式、邏輯。

這樣一來,各組件只需要處理組件內的事,外部引用的組件來決定怎麼使用、提供什麼資料給組件,藉由簡單的切分權責,加上前述的由資料決定畫面,就能讓各個組件的任務單一,並且能被重複使用。

# 提升渲染效能

如同前述,在複雜的頁面中,如果頻繁透過操作 DOM 的方式改變畫面,可能會造成全頁面的 Reflow 及 Repaint;不過在使用框架時,開發者不用太擔心這個問題。

原因是在各主流框架的實作中,幾乎都包含了 Virtual Dom 的概念,也就是用 JavaScript 物件來表達當前的頁面結構;藉由與 UI 分離的資料及 Virtual Dom 之間的關係,當資料變動時,事先計算好這次畫面需要變動的地方,如此一來便能抵銷掉無意義的更動,並重複利用已存在的 DOM 元素;當真的要進行 DOM 更新時,也會一次將所有需要更新的局部組件更新,讓效能的耗損盡可能降低。

# 豐富的開發者生態圈

選用熱門框架的優點,包含了能參與豐富的開發者生態圈;各大主流框架,在 GitHub 上都能輕鬆的找到數以千計的眾多套件,從基本組件、互動效果,到快速建立整個專案的模板,你想解決的問題也許剛好有別人早已經解決過,如果合適,自然可以從中擷取前人的智慧,更進一步的增進開發效率

# 參考資料

  • 為什麼現在的前端都在用「框架」?
  • 前端框架簡介