回流和重绘

117 阅读6分钟

1、首先,我们要知道浏览器是如何渲染一个网页的。大致的步骤是:

  • 解析HTML构建DOM树,DOM树是由各种HTML元素组成的一个树形结构。
  • 解析CSS构建CSSOM树,CSSOM树是由各种CSS规则组成的一个树形结构。
  • 将DOM树和CSSOM树结合起来,生成渲染树(Render Tree)。渲染树只包含需要显示在屏幕上的节点,以及它们的样式信息。
  • 布局(Layout),计算每个节点在屏幕上的位置和大小。
  • 绘制(Paint),将每个节点绘制成像素,并显示在屏幕上。

2、重绘和回流都是在渲染过程中发生的,它们都会影响网页的性能和用户体验。下面我们来看看它们分别是什么,以及有什么区别。

重绘(Repaint) :当一个元素的外观发生改变,但不影响它在文档流中的位置时(比如改变背景色、字体颜色、边框颜色等),浏览器就会对该元素进行重绘,重新生成像素并更新屏幕上的内容。重绘不会改变渲染树的结构,只会影响元素的外观。

回流(Reflow) :当一个元素的布局或者几何属性发生改变时(比如改变宽高、边距、定位、显示隐藏等),浏览器就会对该元素及其子元素、后续元素、甚至整个页面进行回流,重新计算它们在文档流中的位置和大小,并重新构建渲染树。回流会改变渲染树的结构,也会影响元素的外观。

3、从上面的定义可以看出,回流比重绘更耗费性能,因为回流涉及到更多的计算和渲染。而且,一次回流往往会引起一次或多次重绘,但重绘不一定会导致回流。所以,在优化网页性能时,我们应该尽量减少回流和重绘的次数和范围。 那么,如何利用重绘和回流来优化性能呢?这里有一些常见的方法:

  • 合并对DOM样式的修改,尽量一次性修改完毕,或者使用css类来修改。
  • 避免频繁访问会导致回流或重绘的属性,如果需要多次使用,可以用变量缓存起来。
  • 避免使用table布局,因为table中的一个小改动可能会导致整个table重新布局。
  • 尽量使用css3的一些属性来实现动画效果,比如transform、transition、opacity等,这些属性可以在合成层(compositor layer)中完成,并不会影响主线程(main thread)。
  • 对于需要频繁操作或者动画效果的元素,可以将其设置为绝对定位或固定定位,使其脱离文档流,减少回流的影响范围。
  • 对于复杂的动画效果,可以使用canvas或者webgl等技术来实现,避免直接操作DOM元素。
  • 使用虚拟DOM或者DocumentFragment等技术,将多次DOM操作合并为一次,减少回流重绘的次数。

4、回流和重绘是浏览器渲染页面的过程中经常发生的现象,它们会影响页面的性能和用户体验。因此,我们有必要了解如何检测回流和重绘的次数,以便优化我们的代码和设计。

有一些方法可以用来检测回流和重绘的次数,下面我会介绍几种常用的方法:

  • 使用Chrome DevTools的Performance面板。这个面板可以记录页面的各种活动,包括回流和重绘。我们可以在这个面板上看到每次回流和重绘发生的时间、持续时间、原因、影响范围等信息。我们还可以通过设置一些过滤条件,来只显示回流和重绘相关的活动。具体的操作步骤可以参考这个网站。
  • 使用Chrome DevTools的Rendering面板。这个面板可以让我们实时地观察页面的回流和重绘情况。我们可以在这个面板上开启一些选项,比如Paint flashing、Layout Shift Regions、Layer borders等,来高亮显示页面中发生回流和重绘的区域。具体的操作步骤可以参考这个网站。
  • 使用JavaScript代码来监听回流和重绘事件。这个方法需要我们在代码中插入一些监听函数,来捕获回流和重绘事件,并记录它们的次数、时间等信息。这个方法比较灵活,但也比较复杂,需要我们对浏览器的渲染机制有一定的了解。具体的代码示例可以参考这个网站。

5、如何避免回流和重绘

回流和重绘是浏览器渲染页面的过程中经常发生的现象,它们会影响页面的性能和用户体验。因此,我们有必要了解如何避免回流和重绘,以提高页面的渲染速度。

回流(Reflow)是指当一个元素的布局或者几何属性发生改变时,浏览器就会重新计算它在文档流中的位置和大小,并重新构建渲染树。回流会改变渲染树的结构,也会影响元素的外观。

重绘(Repaint)是指当一个元素的外观发生改变,但不影响它在文档流中的位置时,浏览器就会重新生成像素并更新屏幕上的内容。重绘不会改变渲染树的结构,只会影响元素的外观。

从上面的定义可以看出,回流比重绘更耗费性能,因为回流涉及到更多的计算和渲染。而且,一次回流往往会引起一次或多次重绘,但重绘不一定会导致回流。所以,在优化网页性能时,我们应该尽量减少回流和重绘的次数和范围。

那么,如何避免回流和重绘呢?这里有一些常见的方法:

  • 合并对DOM样式的修改,尽量一次性修改完毕,或者使用css类来修改。
  • 避免频繁访问会导致回流或重绘的属性,如果需要多次使用,可以用变量缓存起来。
  • 避免使用table布局,因为table中的一个小改动可能会导致整个table重新布局。
  • 尽量使用css3的一些属性来实现动画效果,比如transform、transition、opacity等,这些属性可以在合成层(compositor layer)中完成,并不会影响主线程(main thread)。
  • 对于需要频繁操作或者动画效果的元素,可以将其设置为绝对定位或固定定位,使其脱离文档流,减少回流的影响范围。
  • 对于复杂的动画效果,可以使用canvas或者webgl等技术来实现,避免直接操作DOM元素。
  • 使用虚拟DOM或者DocumentFragment等技术,将多次DOM操作合并为一次,减少回流重绘的次数