Browser
渲染原理
一、浏览器渲染 HTML 的过程(简化版)
当浏览器加载一个 HTML 页面时,大致经历以下几个阶段:
-
解析 HTML,构建 DOM 树
- 浏览器从上到下解析 HTML,生成 DOM(Document Object Model)。
-
解析 CSS,构建 CSSOM 树
- 解析
<style>、外链 CSS 等资源,构建 CSSOM(CSS Object Model)。
- 解析
-
合并 DOM 和 CSSOM,生成 Render Tree
- 每个可见节点(如 display: none 不会参与)根据样式生成渲染树节点。
-
布局(Layout)阶段
- 又称 回流(Reflow),计算每个节点的几何位置和大小。
-
绘制(Paint)阶段
- 又称 重绘(Repaint),将每个节点的像素信息绘制到屏幕上。
-
分层和合成(Compositing)
- 复杂的节点(如 3D、transform、动画)会单独分层,由 GPU 合成最终页面。
二、回流(Reflow)与重绘(Repaint)
| 概念 | 回流(Reflow) | 重绘(Repaint) |
|---|---|---|
| 触发条件 | DOM 结构变化、元素位置/大小变化、字体改变 | 元素样式变化(颜色、visibility等) |
| 影响范围 | 当前节点及其子树,可能影响整个文档 | 只影响外观,不影响布局 |
| 性能消耗 | 较高 | 较低 |
| 示例 | 改变 width、padding、display | 改变 color、background-color |
三、基于回流和重绘的常见前端性能优化技巧
-
减少回流频率
- 合并多次 DOM 操作
// 不推荐 for (let i = 0; i < 1000; i++) { list.appendChild(createItem(i)); } // 推荐:使用 DocumentFragment const fragment = document.createDocumentFragment(); for (let i = 0; i < 1000; i++) { fragment.appendChild(createItem(i)); } list.appendChild(fragment);- 使用 className 替代多个 style 操作
// 多次触发重绘 + 回流 el.style.width = '100px'; el.style.height = '100px'; // 推荐 el.className = 'my-style';- 避免逐帧同步读取 layout 信息
// 错误做法(会强制回流) const height = el.offsetHeight; el.style.height = height + 'px'; -
使用虚拟 DOM/批量更新框架
React、Vue 等框架有 diff 算法和异步批量更新,能减少不必要的回流。
- 使用 will-change 让浏览器提前优化
.card {
will-change: transform;
}适用于即将频繁变化的属性(如动画中的 transform, opacity)。
-
使用
transform/opacity替代影响布局的属性-
transform:translateX()vsleft: 100px:前者只触发合成,不回流也不重绘。 -
opacity动画比 background-color 更轻量(硬件加速)。
-
总结
浏览器渲染过程核心包括:DOM 解析 → CSSOM 解析 → Render Tree 构建 → 回流 → 重绘 → 合成
回流和重绘频繁发生会严重影响性能,关键是减少 DOM 操作频率、批量处理、尽量避免触发布局计算。
利用虚拟 DOM、硬件加速、动画优化等方式能显著提升性能。