Skip to content

03. 浏览器渲染机制中的重绘与重排

1. 浏览器渲染流程概述

现代浏览器采用流水线式渲染机制,主要分为以下阶段:

其中布局计算阶段对应「重排」,绘制阶段对应「重绘」。这两个阶段共同构成浏览器渲染性能优化的核心关注点。

2. 重排(Reflow)

2.1 定义与触发条件

当 DOM 元素的几何属性发生改变时,浏览器需要重新计算元素位置和大小,这个过程称为重排。常见触发场景包括:

  1. 改变窗口尺寸
  2. 修改元素尺寸(width/height/padding/margin)
  3. 调整元素位置(position/float)
  4. 内容变化(文本长度/图片大小)
  5. 操作 DOM 结构(添加/删除节点)
  6. 获取布局信息(offset*/scroll*/client*)

2.2 性能消耗公式

单个元素的布局变化可能引发级联计算:

总重排时间=i=1n(Ci×Di)\text{总重排时间} = \sum_{i=1}^{n} (C_i \times D_i)

其中:

  • CiC_i = 元素复杂度系数
  • DiD_i = DOM 层级深度

3. 重绘(Repaint)

3.1 定义与触发条件

当元素视觉样式发生变化但不影响布局时,浏览器只需重新绘制受影响区域。常见触发场景:

  1. 颜色改变(color/background-color)
  2. 边框样式调整(border-style/box-shadow)
  3. 透明度变化(opacity)
  4. 背景图片替换
  5. visibility 属性修改

3.2 渲染层优化

浏览器通过分层机制优化重绘:

4. 关键差异对比

特性重排重绘
触发条件布局相关属性改变视觉样式改变
计算范围影响相关 DOM 子树仅当前元素
性能消耗高(触发后续重绘)较低
优化策略批量读写/虚拟DOM提升为合成层
强制触发场景获取布局属性值无强制触发

5. 性能优化实践

5.1 减少重排策略

javascript
// Bad practice
for(let i = 0; i < 100; i++) {
    element.style.width = `${i}px`;
}

// Good practice
const fragment = document.createDocumentFragment();
for(let i = 0; i < 100; i++) {
    const clone = element.cloneNode();
    clone.style.width = `${i}px`;
    fragment.appendChild(clone);
}
document.body.appendChild(fragment);

5.2 优化重绘方法

css
/* 创建独立合成层 */
.optimized-element {
    will-change: transform;
    transform: translateZ(0);
}

5.3 现代API应用

javascript
// 使用requestAnimationFrame批处理
function batchUpdate() {
    requestAnimationFrame(() => {
        // 批量样式修改
    });
}

6. 调试工具使用

Chrome DevTools 的 Performance 面板可捕获渲染时间线:

text
1. 打开 Performance 面板
2. 开始录制
3. 执行页面操作
4. 分析 Timeline 中的
   - Layout(紫色区块)
   - Paint(绿色区块)

理解重排与重排的区别,需要结合浏览器架构演进。现代浏览器采用「合成器线程」进行优化,通过层压缩(Layer Squashing)和异步光栅化(Async Rasterization)等技术,将重排影响范围限制在特定渲染层,显著提升了页面渲染效率。