## CSS解析,構建CSSOM
### 生成CSS規則
同理,CSS規則樹的生成也是類似。簡述為:
```
Bytes → characters → tokens → nodes → CSSOM
```
譬如`style.css`內容如下:
```
body { font-size: 16px }
p { font-weight: bold }
span { color: red }
p span { display: none }
img { float: right }
```
那么最終的CSSOM樹就是:

### 構建渲染樹
當DOM樹和CSSOM都有了后,就要開始構建渲染樹了
一般來說,渲染樹和DOM樹相對應的,但不是嚴格意義上的一一對應
因為有一些不可見的DOM元素不會插入到渲染樹中,如head這種不可見的標簽或者`display: none`等
整體來說可以看圖:

### 渲染
有了render樹,接下來就是開始渲染,基本流程如下:

圖中重要的四個步驟就是:
```
1. 計算CSS樣式
2. 構建渲染樹
3. 布局,主要定位坐標和大小,是否換行,各種position overflow z-index屬性
4. 繪制,將圖像繪制出來
```
然后,圖中的線與箭頭代表通過js動態修改了DOM或CSS,導致了重新布局(Layout)或渲染(Repaint)
這里Layout和Repaint的概念是有區別的:
- Layout,也稱為Reflow,即回流。一般意味著元素的內容、結構、位置或尺寸發生了變化,需要重新計算樣式和渲染樹
- Repaint,即重繪。意味著元素發生的改變只是影響了元素的一些外觀之類的時候(例如,背景色,邊框顏色,文字顏色等),此時只需要應用新樣式繪制這個元素就可以了
回流的成本開銷要高于重繪,而且一個節點的回流往往回導致子節點以及同級節點的回流, 所以優化方案中一般都包括,盡量避免回流。
**什么會引起回流?**
1. 頁面渲染初始化
2. DOM結構改變,比如刪除了某個節點
3. render樹變化,比如減少了padding
4. 窗口resize
5. 最復雜的一種:獲取某些屬性,引發回流,
很多瀏覽器會對回流做優化,會等到數量足夠時做一次批處理回流,
但是除了render樹的直接變化,當獲取一些屬性時,瀏覽器為了獲得正確的值也會觸發回流,這樣使得瀏覽器優化無效,包括
(1)offset(Top/Left/Width/Height)
(2) scroll(Top/Left/Width/Height)
(3) cilent(Top/Left/Width/Height)
(4) width, height
(5) 調用了getComputedStyle()或者IE的currentStyle
**回流一定伴隨著重繪,重繪卻可以單獨出現**
所以一般會有一些優化方案,如:
- 減少逐項更改樣式,最好一次性更改style,或者將樣式定義為class并一次性更新
- 避免循環操作dom,創建一個documentFragment或div,在它上面應用所有DOM操作,最后再把它添加到window.document
- 避免多次讀取offset等屬性。無法避免則將它們緩存到變量
- 將復雜的元素絕對定位或固定定位,使得它脫離文檔流,否則回流代價會很高
**注意:改變字體大小會引發回流**
再來看一個示例:
```js
var s = document.body.style;
s.padding = "2px"; // 回流+重繪
s.border = "1px solid red"; // 回流+重繪
s.color = "blue"; // 重繪
s.backgroundColor = "#ccc"; // 重繪
s.fontSize = "14px"; // 回流+重繪
// 添加node 回流+重繪
document.body.appendChild(document.createTextNode('abc!'));
```
- Web 開發筆記
- 從輸入 URL 到頁面加載完成的過程中都發生了什么事情?
- 從瀏覽器接收url到開啟網絡請求線程
- 開啟網絡線程到發出一個完整的http請求
- 從服務器接收到請求到對應后臺接收到請求
- 后臺和前臺的http交互
- http的緩存
- 解析頁面流程
- HTML解析,構建DOM
- CSS解析,構建CSSOM
- 資源外鏈的下載
- CSS的可視化格式模型
- 包含塊(Containing Block)
- 控制框(Controlling Box)
- BFC(Block Formatting Context)
- IFC(Inline Formatting Context)
- 其它
- JS引擎解析過程
- JS的解釋階段
- JS的預處理階段
- JS的執行階段
- 回收機制
- 參考資料
- JavaScript模塊化編程
- AMD
- requireJS
- CommonJS
- UMD
- ES6模塊
- 參考資料
- 使用 JavaScript 實現一門編程語言
- 如何使用 JavaScript 實現一門編程語言(1) —— 前言
- 如何使用 JavaScript 實現一門編程語言(2) —— 編寫一個解析器
- 如何使用 JavaScript 實現一門編程語言(3) —— Input stream
- 如何使用 JavaScript 實現一門編程語言(4) —— Token stream
- 如何使用 JavaScript 實現一門編程語言(5) —— AST
- 如何使用 JavaScript 實現一門編程語言(6) —— Interpreter
- 完整代碼
- 參考資料
- 前端布局概論
- 參考資料
- Windows 筆記
- 錯誤解決
- win10應用商店無法登錄提示0x80070426解決方法
- 使用技巧
- 設置 Hyper-V 和 VMware 共存
- Powershell
- WSL