什么是重绘(Repaint)和回流(Reflow)?如何优化?

一、重绘(Repaint)与回流(Reflow)的定义与区别

1. 重绘(Repaint)
  • 定义:当元素的外观属性(如颜色、背景、可见性等)发生变化,但不影响其在文档流中的布局和几何尺寸时,浏览器会重新绘制该元素,此过程称为重绘。
  • 触发条件
    • 修改颜色、背景色、边框颜色、透明度、阴影等非几何属性。
    • 修改 visibility 属性(如 visibility: hidden)。
  • 性能影响:重绘不涉及布局计算,因此开销较小。
2. 回流(Reflow / Layout)
  • 定义:当元素的布局、几何属性(尺寸、位置、结构)发生变化时,浏览器需重新计算所有受影响元素的几何信息,并更新渲染树,此过程称为回流。
  • 触发条件
    • 增删/移动 DOM 节点。
    • 修改元素尺寸(宽高、边距、边框)或位置(topleft)。
    • 窗口大小改变、字体大小改变、内容变化(如文本长度)。
    • 读写 offsetWidthscrollTop 等布局属性(强制同步计算)。
  • 性能影响:回流涉及整个或部分文档的重新布局计算,开销比重绘大 10 倍以上。
3. 核心区别与联系
特性回流(Reflow)重绘(Repaint)
触发原因布局/几何属性变化外观属性变化(不影响布局)
计算范围部分或整个文档树仅需更新元素外观
性能开销高(需重新布局)低(仅重绘像素)
关联性回流必触发重绘重绘不触发回流
示例修改 widthdisplay: none修改 colorvisibility: hidden

引用说明:


二、优化重绘与回流的方法

1. 减少 DOM 操作
  • 批量修改:使用 DocumentFragment 或离线 DOM(display: none)进行批量操作,完成后一次性插入文档。
  • 避免逐条修改样式:用 class 替代内联样式(如 element.className = "new-style"),或通过 cssText 合并样式修改。
2. 优化样式与布局
  • 使用 GPU 加速属性
    • 用 transform 替代 top/left(动画不触发回流)。
    • 用 opacity 替代 visibilityopacity 可触发 GPU 合成)。
  • 避免触发同步布局
    • 缓存布局属性:如将 offsetWidth 存入变量,避免重复读取。
    • 避免循环中读写布局属性(如先读取所有值,再统一修改)。
3. 分离渲染层
  • 脱离文档流:为动画元素设置 position: absolute/fixed,限制回流范围仅影响自身。
  • 使用 will-change:提示浏览器元素将独立渲染(如 will-change: transform)。
4. 规避高开销操作
  • 避免 table 布局table 的局部修改可能触发全局回流。
  • 用 visibility 替代 display: none
    • display: none 触发回流 + 重绘;visibility: hidden 仅触发重绘。
  • 慎用 CSS 表达式(expression :每次渲染都会重新计算。
5. 利用浏览器优化机制
  • 防抖/节流:对 resizescroll 事件进行节流,减少回流频率。
  • 现代 CSS 方案
    • Flexbox/Grid 布局比传统布局回流更少。
    • 使用 contain: strict 限制元素影响范围。

三、关键场景示例

1. 动画优化
// ❌ 低效:每次修改 top 触发回流  
element.style.top = `${top++}px`;  

// ✅ 高效:使用 transform(不触发回流)  
element.style.transform = `translateY(${top}px)`;  

 2. 批量 DOM 操作

// ❌ 逐条插入节点触发多次回流  
list.forEach(item => container.appendChild(item));  

// ✅ 使用 DocumentFragment 批量插入  
const fragment = document.createDocumentFragment();  
list.forEach(item => fragment.appendChild(item));  
container.appendChild(fragment);  
3. 样式修改对比
// ❌ 多次修改内联样式  
element.style.color = "red";  
element.style.background = "blue";  

// ✅ 通过 class 或 cssText 合并  
element.className = "new-style";  
// 或  
element.style.cssText = "color:red; background:blue;";  

四、总结

  • 核心原则回流 > 重绘 > 无操作,优先避免回流,其次减少重绘。
  • 性能工具:使用 Chrome DevTools 的 Performance 面板检测回流/重绘事件,Layers 面板检查渲染层分离效果。
  • 框架优化:在 Vue/React 中,v-show 比重绘(仅修改 display),v-if 比回流(增删节点)更高效。

通过上述策略,可显著提升页面渲染性能,尤其在复杂交互或动画场景中效果显著。

JavaScript 中,repaint回流reflow)是与浏览器渲染相关的两个概念。 指的是当元素样式发生改变,但不影响其布局时,浏览器会根据新的样式制这个元素的过程。并不会引起页面的新布局,只是改变了元素的外观。 回流指的是当 DOM 结构发生改变或者元素的布局属性发生改变时,浏览器需要新计算元素的几何属性(位置、大小等),然后新构建渲染树,这个过程就叫做回流回流会导致页面的新布局,比如改变元素的宽高、位置、添加或删除元素等操作都会引起回流。 由于回流涉及到新计算元素的几何属性以及新构建渲染树,所以比的代价要高。频繁的回流操作会导致页面性能下降,因此在编写 JavaScript 代码时需要尽量避免频繁的回流操作。 为了减少回流,可以采取以下措施: 1. 使用 CSS3 的 transform 属性来替代 top/left 来进行位置调整,因为 transform 不会引起回流。 2. 对需要多次的元素,使用绝对定位(position: absolute)进行脱离文档流操作,然后再进行修改。 3. 批量修改样式时,可以先将元素的 display 属性设置为 none,然后再进行修改,最后再将 display 属性还原,这样可以减少回流次数。 4. 将需要多次操作的 DOM 元素缓存起来,减少对 DOM 的访问次数。 通过了解回流的概念,并采取相应的优化措施,可以提高页面的性能用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

破碎的天堂鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值