什么是重绘,什么是回流?如何减少回流?
重绘(Repaint)
重绘是指当页面中某些元素的外观(如颜色、背景、边框等)发生改变,但不影响其布局(尺寸和位置)时,浏览器会重新绘制这些元素。
重绘的过程不会影响元素在页面中的布局,因此性能消耗相对较小。
触发重绘的操作:
- 修改颜色(color、background-color)
- 修改可见性(visibility)
- 修改阴影(box-shadow)
- 修改透明度(opacity)
- 等不改变布局的样式修改
回流(Reflow)
回流(也称为重排)是指当页面中的元素布局(尺寸、位置)发生改变时,浏览器需要重新计算元素的几何属性并重新排列元素。回流比重绘消耗更多的性能资源,因为它涉及到元素位置和尺寸的重新计算。
当发生回流时,通常也会导致重绘,但重绘不一定会引起回流。
触发回流的操作:
- DOM 元素的添加、删除或修改
- 改变元素的尺寸(width、height、padding、margin、border)
- 改变元素的位置(position、top、left、right、bottom)
- 改变元素的内容(文本、图片等)
- 改变浏览器窗口大小(resize 事件)
- 计算或读取某些属性(offsetWidth、offsetHeight、clientWidth、clientHeight、scrollWidth、scrollHeight、getComputedStyle()等)
- 设置 style 属性的值
- 激活 CSS 伪类(如 :hover)
如何减少回流
由于回流会显著影响性能,所以应尽量减少回流操作。以下是一些减少回流的方法:
1. 批量修改 DOM
避免逐条修改 DOM,而是使用文档片段(DocumentFragment)或者一次性修改。
2. 使用 CSS 类一次性修改样式
3. 脱离文档流进行操作
对元素进行复杂操作时,可以先使其脱离文档流,操作完成后再放回去。
4. 避免频繁读取会引发回流的属性
读取一些布局属性(如 offsetTop、scrollTop 等)会强制浏览器进行回流计算。如果需要多次使用这些值,应该一次性读取并保存。
5. 使用 transform 和 opacity 进行动画
CSS 的 transform 和 opacity 属性通常不会触发回流,只会触发重绘,而且现代浏览器通常会对这些操作进行硬件加速。
6. 使用 requestAnimationFrame 控制动画帧
7. 合理使用节流和防抖
对于频繁触发的事件(如 resize、scroll 等),使用节流(throttle)或防抖(debounce)技术限制事件处理函数的执行频率。
8. 使用 will-change 属性提示浏览器
对于即将发生变化的元素,可以使用 will-change 属性提前告知浏览器,让浏览器进行优化。
注意:will-change 属性不应过度使用,只对确实需要优化的元素使用。
总结
- 重绘是指元素外观改变但不影响布局的渲染过程
- 回流是指元素布局(尺寸、位置)改变导致的渲染过程
- 回流比重绘更消耗性能,回流一定会导致重绘,但重绘不一定会导致回流
- 减少回流的方法包括:批量修改 DOM、使用 CSS 类、脱离文档流操作、避免频繁读取布局属性、使用 transform 和 opacity 进行动画、使用 requestAnimationFrame、合理使用节流和防抖、使用 will-change 属性等
