重绘和回流

重绘(Repaint)和回流(Reflow)


重绘和回流会在我们设置节点样式时频繁出现,同时也会很大程度上影响性能。

重绘是当节点需要更改外观而不会影响布局的,比如改变 color 就叫称为重绘

回流是布局或者几何属性需要改变就称为回流。

回流必定会发生重绘,重绘不一定会引发回流。回流所需的成本比重绘高的多,改变父节点里的子节点很可能会导致父节点的一系列回流。

以下几个动作可能会导致性能问题:

改变 window 大小
改变字体
添加或删除样式
文字改变
定位或者浮动
盒模型

重绘和回流其实也和 Eventloop 有关。
1.当 Eventloop 执行完 Microtasks 后,会判断 document 是否需要更新,因为浏览器是 60Hz 的刷新率,每 16.6ms 才会更新一次。

2.然后判断是否有 resize 或者 scroll 事件,有的话会去触发事件,所以 resize 和 scroll 事件也是至少 16ms 才会触发一次,并且自带节流功能。

3.判断是否触发了 media query

4.更新动画并且发送事件

5.判断是否有全屏操作事件

6.执行 requestAnimationFrame 回调

7.执行 IntersectionObserver 回调,该方法用于判断元
素是否可见,可以用于懒加载上,但是兼容性不好

8.更新界面

9.以上就是一帧中可能会做的事情。如果在一帧中有空闲时间,就会去执行 requestIdleCallback 回调。

减少重绘和回流


使用 transform 替代 top

使用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流(改变了布局)

不要把节点的属性值放在一个循环里当成循环里的变量

for(let i = 0; i < 1000; i++) {
    // 获取 offsetTop 会导致回流,因为需要去获取正确的值
    console.log(document.querySelector('.test').style.offsetTop)
}

不要使用 table 布局,可能很小的一个小改动会造成整个 table 的重新布局

动画实现的速度的选择,动画速度越快,回流次数越多,也可以选择使用 requestAnimationFrame

CSS 选择符从右往左匹配查找,避免节点层级过多

将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点。比如对于 video 标签来说,浏览器会自动将该节点变为图层。

设置节点为图层的方式有很多,我们可以通过以下几个常用属性可以生成新图层

will-change
video、iframe 标签

你可能感兴趣的:(重绘和回流)