性能优化与调试技巧(减少重绘和重排) | 青训营

154 阅读3分钟

本文主要介绍如何减少重绘与重排,来提高 JavaScript 在浏览器中的执行效率。

什么是重绘与重排?

在了解如何优化JavaScript代码来提高性能之前,让我们先了解一下重绘和重排的概念:

重绘是什么:重新绘制。当 DOM 元素样式的改变影响了元素的可见性、但没有改变它在文档流中的位置时,浏览器会重新绘制该元素,以便反映样式的变化。重绘通常是影响性能的一种情况,因为它会引起不必要的图形重新绘制。

重排是什么:重新生成布局。当DOM 的变化影响了元素的几何属性(宽和高)--比如改变边框宽度或给段落增加文字导致行数增加--浏览器需要重新计算元素的几何属性,同样其他元素的几何属性和位置也会因此受到影响。浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树。这个过程称为重排。

重排与重绘的关系

重排一定会导致重绘,重绘不一定导致重排。如果DOM变化不影响几何属性,元素的布局没有改变,则只发生一次重绘(不需要重排)。

导致重绘与回流的常见操作

以下是一些常见导致重绘与回流的操作:

  1. DOM 操作:频繁地对 DOM 进行增删改查操作。
  2. 样式操作:修改元素的样式,特别是通过操作 style 属性。
  3. 布局属性读取:读取元素的尺寸或位置信息,如 offsetTopoffsetLeftclientWidthclientHeight 等。
  4. 获取布局信息:获取布局相关的属性,如 scrollTop 和 scrollLeft
  5. 修改布局属性:修改元素的尺寸或位置,如改变元素的宽度、高度、内外边距等。
  6. 窗口大小变化:当浏览器窗口大小改变时,会导致整个页面的回流。

对性能的影响

重排和重绘会不断触发,这是不可避免的。但是,它们非常耗费资源,是导致网页性能低下的根本原因。

提高网页性能,就是要降低"重排"和"重绘"的频率和成本,尽量少触发重新渲染。

优化策略

1. 尽量不要把读操作和写操作,放在一个语句里面。

// 错误示例
div.style.left = div.offsetLeft + 10 + "px";
div.style.top = div.offsetTop + 10 + "px";

// 优化后
var left = div.offsetLeft;
var top  = div.offsetTop;
div.style.left = left + 10 + "px";
div.style.top = top + 10 + "px";

2. 使用 class 进行样式修改

通过添加或移除 class 来修改样式,而不是直接操作 style 属性。这样会减少重绘次数。

// 错误示例 
for (let i = 0; i < 1000; i++) {
  element.style.color = 'red';
}

// 优化后
for (let i = 0; i < 1000; i++) {
  element.classList.add('highlight');
}

3.批量 DOM 操作

频繁地对 DOM 进行增删改查会导致多次重绘和重排。相反,你可以将多个 DOM 操作合并成一个批量操作。

4. 缓存布局属性读取结果

避免在循环中多次读取布局属性,可以先将其存储在变量中。

// 错误示例 
for (let i = 0; i < elements.length; i++) {
  const top = elements[i].offsetTop;
  // 使用 top 做一些操作...
}

// 优化后 
for (let i = 0; i < elements.length; i++) {
  const element = elements[i];
  const top = element.offsetTop;
}

5. 使用 requestAnimationFrame

对于需要进行大量计算或动画的操作,使用 requestAnimationFrame 来执行,这样可以优化动画性能,并在一帧中完成所有重绘与重排操作。

最后如果本篇文章有错误或问题,欢迎指正,谢谢!!!
参考文章

[如何优化 JavaScript 性能:减少重绘与回流]