# DOM
# 簡介
DOM (document object model,文件物件模型) 由 W3C (world wide web consortium) 定義,DOM 將 HTML 內的所有 element 定義成物件,並以樹狀結構表示。
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 上都能輕鬆的找到數以千計的眾多套件,從基本組件、互動效果,到快速建立整個專案的模板,你想解決的問題也許剛好有別人早已經解決過,如果合適,自然可以從中擷取前人的智慧,更進一步的增進開發效率
# 參考資料
- 為什麼現在的前端都在用「框架」?
- 前端框架簡介