重排(Reflow),重绘(Repaint),Composite(合成)

概念

重排(Reflow)是指浏览器在渲染页面时,根据DOM结构和CSS样式计算元素的布局和几何属性的过程。当页面中的元素发生变化(如添加、删除或修改元素),或者浏览器窗口大小改变时,都会触发重排操作。重排是一个比较耗费性能的操作,因为它会影响到整个页面的布局。

重绘(Repaint)是指浏览器进行渲染时,根据计算好的布局信息,将元素绘制成像素的过程。当元素的外观属性(如颜色、背景、边框等)发生变化时,会触发重绘操作。与重排不同,重绘只涉及到元素外观的更改,而不会影响到布局。

合成(Composite)是指浏览器根据页面的层次结构和元素的绘制顺序,将多个图层按照正确的顺序合并成最终的页面显示。这个过程发生在 GPU(图形处理单元)上,可以充分利用硬件加速,提高渲染性能。合成操作是在重排和重绘完成后进行的,以确保页面显示的准确性。

性能

  1. 重排 是重新计算元素布局和几何属性的过程,比较耗费性能。
  2. 重绘 是根据计算好的布局信息将元素绘制成像素的过程,只涉及外观属性的更改。
  3. 合成 是将多个图层按照正确的顺序合并成最终页面显示的过程,发生在 GPU 上,可以提高渲染性能。

所以说,尽量避免重绘的方法之一,就是用合成代替重绘。

哪些是合成

最典型的合成就是 transform: translate
transform:包括 translate、scale、rotate 等变换函数
opacity:用于调整元素的透明度
filter:应用图像过滤效果,如模糊、饱和度等
backdrop-filter:应用背景过滤效果,如模糊、饱和度等
will-change:明确告知浏览器该元素即将发生变化,可以提前进行合成处理
mix-blend-mode:定义了元素与其父元素或其他兄弟元素的混合模式

这些属性或特性通过 GPU 加速执行,避免了重排和重绘的开销,从而提高性能。它们可以有效地在动画、过渡和视觉效果中使用,特别是对于频繁更新的元素操作,如移动、缩放和淡入淡出等。

请注意,虽然这些属性通常被视为合成操作,但具体实现可能因浏览器和硬件而异。有时,某些复杂的情况下仍可能触发重排或重绘操作。因此,在优化性能时,我们仍然需要考虑其他因素,如合理的 HTML 结构、优化网络请求等。

避免重排

重排->合成

  1. transform
  2. 使用 CSS 属性进行动画效果: 尽量使用 CSS3 的过渡(transition)和动画(animation)属性来实现动画效果,而不是使用 JavaScript 定时器或 requestAnimationFrame。CSS 动画更高效,可以利用硬件加速。

重排->重绘

  1. opacity

预判以减少重排

  1. 使用 CSS 布局技巧,如 Flexbox 和 Grid,可以帮助避免一些常见的重排情况,并提高布局的性能。

批量修改使得重排只发生一次

  1. 批量修改样式: 避免在 JavaScript 中直接修改样式属性,而是尽量通过修改 CSS 类名来一次性批量修改样式。因为每次修改样式都会引发重排和重绘操作,而批量修改只会触发一次。
  2. 使用文档片段(Document Fragment): 在需要插入大量节点时,可以先将这些节点添加到文档片段中,然后再把整个文档片段添加到文档中。这样可以减少多次插入节点引起的重排。
  3. 使用虚拟 DOM 技术: 虚拟 DOM 技术可以帮助优化渲染性能,通过比较虚拟 DOM 树与实际 DOM 树之间的差异,最小化实际 DOM 的修改和重排。

其他

  1. 避免频繁访问布局信息: 避免在 JavaScript 中频繁地读取布局相关属性(如 offsetTop、offsetLeft、clientWidth 等)。如果需要多次使用某个值,应将其缓存到变量中,以减少重复计算。
  2. 缓存 DOM 访问: 通过将频繁访问的 DOM 元素缓存到变量中,可以减少对 DOM 树的遍历次数,从而减少重排的开销。

2023/7/17 17:57:36

为什么读取offsetTop等属性也会触发重排

2023/7/17 17:57:51

读取 offsetTop 等属性会触发重排的原因是,这些属性涉及到元素的布局信息,需要浏览器进行实时计算。

当你读取像 offsetTop、offsetLeft、offsetWidth、offsetHeight 这些属性时,浏览器需要确定该元素在文档流中的位置,以及其相对于父元素的偏移量。这涉及到重新计算元素的布局信息,包括位置、尺寸、盒模型等。

由于布局是相互关联的,改变一个元素的布局信息可能会影响其他元素的布局,因此浏览器需要进行重排操作来确保页面的正确渲染。这意味着浏览器会重新计算受影响元素的位置和尺寸,并更新整个页面的布局。

因此,在性能敏感的情况下,频繁地读取 offsetTop 等属性可能会导致不必要的重排,从而降低页面的性能。为了最小化重排的次数,可以考虑将这些属性的值缓存起来,避免多次读取同一属性的操作。或者,使用更高效的方式来获取元素的位置和尺寸信息,例如使用 getBoundingClientRect() 方法,它返回一个包含元素位置和尺寸信息的 DOMRect 对象,避免了重复的布局计算。

2023/7/17 17:59:08

为什么访问DOM元素也会触发重排

2023/7/17 17:59:29

访问 DOM 元素也可能触发重排的原因是,当你对 DOM 元素进行访问时,浏览器需要确保返回的值是最新、准确的。

在访问 DOM 元素时,例如通过 getElementById、querySelector 等方法获取元素,或者访问元素的属性、样式等,浏览器需要检查该元素的布局信息以及相关的计算结果。如果这些信息尚未计算或已过期,浏览器会触发重排操作来获取最新的信息。

重排涉及到重新计算元素的布局信息,包括位置、尺寸、盒模型等,并可能导致其他元素的布局变化。因此,在访问 DOM 元素时,浏览器必须确保页面的布局是最新的,并执行必要的重排操作。

为了避免不必要的重排,可以采取以下策略:

尽量减少对 DOM 元素的频繁访问,尤其是在循环或动画等性能敏感的情况下。
在可能的情况下,将需要访问的 DOM 元素缓存起来,避免重复的查询操作。
使用批量处理方式,一次性读取多个属性或访问多个元素,以减少触发重排的次数。
考虑使用更高效的方式来获取元素信息,例如使用 getBoundingClientRect() 方法。
使用虚拟 DOM 等技术来最小化对实际 DOM 的直接访问,以提高性能。
综上所述,访问 DOM 元素可能触发重排,因为浏览器需要确保返回的值是最新的,为此需要计算和更新布局信息。通过优化访问方式和减少不必要的查询操作,可以降低重排的频率,提高页面的性能。

减少重绘

你可能感兴趣的:(前端,javascript,html,性能优化)