前言
在网页性能和浏览器渲染方面,重绘和回流是两个非常重要的概念。他们描述了浏览器在页面发生变化时如何重新渲染内容,理解他们有助于编写高效的网页代码。
1. 回流(Reflow)
回流 又叫重排,是指当页面中的元素尺寸、布局、或几何属性发生变化时,浏览器需要重新计算元素的位置和尺寸,并重新生成布局。这一过程会影响页面中所有与变化元素相关的部分,可能导致整个页面重新布局。
什么会触发回流?
- 添加或删除 DOM 元素。比如通过 JavaScript 动态插入、删除元素。
- 改变元素的几何属性。包括宽度、高度、边距、内边距、边框宽度等的变化。
- 修改浏览器窗口大小。当浏览器窗口大小改变时,需要重新计算布局。
- 字体大小的变化 。例如通过 CSS 动态更改
font-size
。 - 滚动操作。当页面滚动时,浏览器需要重新计算可见区域的布局。
- CSS 属性的变化 。一些会影响布局的属性(例如
display
、position
、width
、height
等)发生改变时。
回流的影响
回流是一个非常消耗性能的操作,尤其是在页面元素复杂且层级较深的情况下,因为浏览器需要重新计算布局,并重新绘制所有受影响的元素。如果回流操作频繁,可能会导致页面性能问题,比如卡顿、操作延迟等。
2. 重绘(Repaint)
重绘指的是页面元素的外观(例如颜色、背景、边框样式等)发生变化时,浏览器重新绘制这些元素的过程。重绘不会影响页面的布局,只会重新绘制已经存在的元素。
什么会触发重绘?
- 颜色变化 。例如通过 CSS 修改
color
、background-color
。 - 字体颜色和阴影的变化。
- 透明度变化 。如使用 CSS 的
opacity
属性。 - 边框样式变化 。如
border-color
、border-style
的改变。
重绘的影响
重绘相比回流来说代价较小,因为它只涉及到外观的重新渲染,而不需要重新计算布局和尺寸。然而,在一个复杂的页面中,频繁的重绘操作也会影响性能。
回流与重绘的关系
回流通常会导致重绘,因为在元素的位置或尺寸发生变化后,浏览器不仅需要重新计算布局,还需要重新绘制受影响的元素。然而,重绘不会导致回流,重绘仅仅是重新绘制元素,而不会涉及布局变化。
如何优化回流和重绘?
减少回流和重绘可以显著提升页面性能。以下是一些常见的优化策略:
- 避免逐个修改样式 :如果要更改元素的多个样式属性,最好使用
class
一次性修改,而不是多次修改不同的样式属性。每次修改样式都会触发回流或重绘。
js
// 不推荐
element.style.width = '100px';
element.style.height = '200px';
// 推荐
element.className = 'new-class'; // 一次性修改多个样式
- 批量修改 DOM :尽量减少 DOM 操作的频率。如果需要对多个元素进行修改,可以使用文档片段(DocumentFragment) 或者 离线 DOM (如
display: none
临时隐藏)来减少多次操作对页面性能的影响。 - 避免频繁的读取布局信息 :读取布局信息(如
offsetHeight
、clientWidth
)会触发回流,因为浏览器必须重新计算布局来返回正确的值。尽量缓存这些值,避免在同一帧中反复读取。 - 使用 CSS 动画替代 JavaScript 动画:CSS 动画在浏览器中的执行效率通常比 JavaScript 高,因为它们可以由浏览器的渲染引擎优化,甚至在 GPU 上处理。
- 使用
will-change
优化重绘 :对于即将发生变化的属性(如transform
、opacity
),可以使用will-change
提示浏览器进行优化:
css
.animated {
will-change: transform, opacity;
}
- 减少复杂的选择器:复杂的 CSS 选择器会增加浏览器匹配元素的时间,因此尽量使用简单、高效的选择器。
总结
- 回流 是布局的重新计算,是较为消耗性能的操作,涉及到页面布局变化。
- 重绘 是页面外观的重新绘制,代价小于回流,但频繁重绘也会影响性能。
通过减少不必要的 DOM 操作和样式修改,合理地优化代码,可以有效提升页面的渲染性能。