Blink 渲染数据流
1. 浏览器真正关心的是数据,而不是流程
不要记:
1 | DOM |
应该记:
1 | DOM Node |
每一步都是:
输入 → 计算 → 输出新的数据。
2. 每个阶段负责什么
① DOM Node
职责:
- 保存 HTML 结构
- 父子关系
- 属性(Attribute)
例如:
1 | <div>Hello</div> |
对应:
1 | Node(div) |
DOM 不负责:
- x
- y
- width
- height
- 绘制
② Style(Computed Style)
职责:
保存元素最终样式。
例如:
1 | background:red; |
这里只负责:
元素应该长什么样。
不负责:
放在哪里。
③ LayoutObject
职责:
保存布局结果(Geometry)。
例如:
1 | x |
Layout 的作用:
根据 Style 计算几何信息。
Layout 的输出:
1 | LayoutObject |
④ Paint
输入:
1 | Geometry(LayoutObject) |
Paint 做什么?
把每个 Layer 画出来。
输出:
1 | PaintArtifact |
可以理解成:
1 | Layer1 |
不是最终屏幕。
⑤ Composite
输入:
1 | 所有 Layer 的 PaintArtifact |
负责:
- 合成 Layer
- transform
- opacity
- z-index
- GPU 合成
输出:
1 | CompositorFrame |
最终交给 GPU。
3. 数据流
真正应该记住的是:
1 | HTML |
4. Dirty(失效)机制
浏览器不是:
从头重新执行。
而是:
找到最早失效的数据。
然后:
1 | 从这里重新开始 |
例如:
修改 background
1 | div.style.background="red"; |
影响:
1 | Style Dirty |
不会:
1 | Layout Dirty |
因为:
Geometry 没变。
修改 width
1 | div.style.width="200px"; |
影响:
1 | Style Dirty |
因为:
Geometry 改了。
修改 transform(独立 Layer)
1 | div.style.transform="translateX(...)"; |
影响:
1 | Composite Dirty |
通常:
1 | Layout |
5. LayoutObject 不是 DOM
DOM:
1 | <div>Hello</div> |
DOM:
1 | div |
Layout:
1 | LayoutBlock |
职责不同:
DOM:
HTML 结构
LayoutObject:
几何信息
6. 为什么需要 LayoutObject?
因为:
DOM 不应该保存:
1 | width |
这些属于:
Layout。
所以 Blink:
1 | Node |
而不是:
1 | Node |
7. 不是每个 DOM Node 都有 LayoutObject
例如:
1 | <div> |
DOM:
1 | div |
LayoutObject:
1 | LayoutBlock(div) |
Comment:
×
Script:
×
原因:
它们不会参与布局。
8. Paint 不创建 Layer
顺序是:
1 | Render Tree |
Paint:
使用 Layer。
不是:
创建 Layer。
9. Paint 的输入与输出
输入:
1 | Geometry |
输出:
1 | PaintArtifact |
可以理解为:
1 | Layer1图片 |
Composite:
就是组合这些图片。
10. 删除一个 DOM 节点发生什么?
例如:
1 | box.remove(); |
立即:
1 | DOM Node |
对应:
1 | LayoutObject |
下一次 Rendering Opportunity:
1 | 旧 PaintArtifact |
不是:
Paint 对象删除。
而是:
Paint 的结果失效,重新生成。
11. 当前已经建立的完整模型
1 | HTML |
每一次修改,本质都是:
1 | 修改数据 |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 YianNotes!

