什么是重绘和重排? 如何去避免?
Posted °PJ想做前端攻城狮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了什么是重绘和重排? 如何去避免?相关的知识,希望对你有一定的参考价值。
前言
面试官:既然你刚刚提到了重绘和重排,那就说一说吧。
我:。。。💥
我们首先来回顾一下渲染流水线
的流程:
回流
首先介绍回流
。回流
也叫重排
。
触发条件
简单来说,就是当我们对 DOM 结构的修改引发 DOM 几何尺寸变化
的时候,会发生回流
的过程。比如以下情况
- 一个 DOM 元素的几何属性变化,常见的几何属性有
width
、height
、padding
、margin
、left
、top
、border
等等, 这个很好理解。 - 使 DOM 节点发生
增减
或者移动
。 - 读写
offset
族、scroll
族和client
族属性的时候,浏览器为了获取这些值,需要进行回流操作。 - 调用
window.getComputedStyle
方法。
回流过程
依照上面的渲染流水线,触发回流的时候,如果 DOM 结构发生改变,则重新渲染 DOM 树,然后将后面的流程(包括主线程之外的任务)全部走一遍。
相当于将解析和合成的过程重新又走了一遍,开销是非常大的。
重绘
触发条件
当 DOM 的修改导致了样式的变化
,并且没有影响几何属性的时候
,会导致重绘
(repaint
)。
重绘过程
由于没有导致 DOM 几何属性的变化,因此元素的位置信息不需要更新,从而省去布局的过程。流程如下:
跳过了生成布局树
和建图层树
的阶段,直接生成绘制列表,然后继续进行分块、生成位图等后面一系列操作。
所以说:重绘不一定导致回流,但回流一定发生了重绘
。
合成
这是我们可能不太熟悉的一种情况,是直接合成
。比如利用 CSS3 的transform
、opacity
、filter
这些属性就可以实现合成的效果,也就是大家常说的GPU加速。
GPU加速的原因
在合成的情况下,会直接跳过布局和绘制流程,直接进入非主线程
处理的部分,即直接交给合成线程
处理。交给它处理有两大好处:
- 能够充分发挥
GPU
的优势。合成线程生成位图的过程中会调用线程池,并在其中使用GPU
进行加速生成,而GPU 是擅长处理位图数据的。 - 没有占用主线程的资源,即使主线程卡住了,效果依然能够流畅地展示。
总结
知道上面的原理之后,对于开发过程有什么指导意义呢?
- 避免频繁使用 style,而是采用修改
class
的方式。 - 使用
createDocumentFragment
进行批量的 DOM 操作。 - 对于 resize、scroll 等进行防抖/节流处理。
- 添加 will-change: tranform ,让渲染引擎为其单独实现一个图层,当这些变换发生时,仅仅只是利用合成线程去处理这些变换,而不牵扯到主线程,大大提高渲染效率。当然这个变化不限于
tranform
, 任何可以实现合成效果的 CSS 属性都能用will-change
来声明。
以上是关于什么是重绘和重排? 如何去避免?的主要内容,如果未能解决你的问题,请参考以下文章