重绘和回流


重绘和回流是前端性能优化中的两个重要概念,对网站性能有着深远的影响。

重绘(Repaint)

重绘指的是当元素样式的改变不影响布局时,浏览器会重新绘制这个元素,但不会影响其他元素的位置和尺寸,这个过程也称为“重画”。重绘操作通常由JavaScript脚本或CSS动画引起。

例如,在下面的HTML代码中,我们将元素的颜色从红色改为绿色:

1
2
3
4
5
<div style="color: red;">Hello, world!</div>

<script>
document.querySelector('div').style.color = 'green';
</script>

在执行上述代码时,浏览器将重新绘制 <div> 元素,以反映其新的样式设置,但不会改变其位置和大小。

回流(Reflow)

回流指的是当元素的尺寸、位置或内容发生改变时,浏览器需要重新计算布局,并重新排列其他相关元素,这个过程也称为“重排”。回流操作通常由以下事件引起:

  • 页面首次渲染。
  • 浏览器窗口大小发生改变。
  • 元素尺寸、位置或内容发生改变。
  • 添加或删除DOM元素。

例如,在下面的 HTML 代码中,我们将元素的宽度从 100px 改为 200px:

1
2
3
4
5
<div style="width: 100px;">Hello, world!</div>

<script>
document.querySelector('div').style.width = '200px';
</script>

在执行上述代码时,浏览器将重新计算布局,并重新排列其他相关元素,以适应 <div> 元素的新宽度。

重绘和回流的区别

  • 重绘是指浏览器需要重新绘制一个元素,但不会影响其他元素的位置和尺寸;回流是指浏览器需要重新计算页面布局,并重新排列其他相关元素。
  • 重绘通常由JavaScript脚本或CSS动画引起;回流通常由页面首次渲染、浏览器窗口大小发生改变、元素尺寸、位置或内容发生改变、添加或删除DOM元素等事件引起。
  • 回流比重绘更加耗费性能,因为它需要重新计算布局,并重新排列其他相关元素。因此,在前端开发中,我们应该尽量避免回流操作,控制好DOM树的深度和复杂度,以提高网站的性能和用户体验。

减少重绘和回流

  • 减少 DOM 操作

DOM 操作往往会导致浏览器进行重排和重绘操作,并且在大型应用程序中使用过多的 DOM 操作会降低性能。因此,应该尽量避免不必要的 DOM 操作。例如,可以将多个 DOM 操作合并为一个批处理操作。

  • 缓存布局信息

获取元素的位置和尺寸等布局信息需要进行回流操作,因此在需要使用这些信息时,最好将其缓存起来以减少回流次数。例如,可以使用getBoundingClientRect()方法获取元素的位置和尺寸信息,并将其存储在变量中以供将来使用。

1
2
const element = document.querySelector('.my-element');
const rect = element.getBoundingClientRect();
  • 使用 CSS 动画

CSS 动画可通过 GPU 加速,从而减少了浏览器的工作负担,提高了动画的性能。而 JavaScript 实现的动画则需要更多的计算资源,并可能导致重绘和回流操作。因此,在可能的情况下,应尽量使用 CSS 动画。

  • 避免频繁的样式改变

频繁改变元素的样式可能会导致浏览器频繁进行重绘和回流操作。因此,应尽量避免频繁改变元素的样式。例如,可以将多个样式合并为一个类,然后通过更改元素的类来一次性地更改样式。

  • 使用虚拟 DOM

虚拟 DOM 可以将多个 DOM 操作合并为一个批处理操作,并最小化重排和重绘操作,从而提高页面性能。在某些框架中,如 React 和 Vue.js,使用虚拟 DOM 已成为标准做法。

总之,减少重绘和回流操作是网站性能优化中的关键步骤之一。通过合理编写代码,避免不必要的 DOM 操作和频繁的样式改变等操作,可以有效地减少重绘和回流的次数,提高网站的性能和用户体验。