重排和重绘

193 阅读3分钟

重排和重绘

1. 举例说明什么是“重排”“重绘”和“合成”

  • 重排:
    • 当DOM的变化影响了元素的几何信息(元素的的位置和尺寸大小),浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置,这个过程叫做重排。
    • 重排也叫回流,简单的说就是重新生成布局,重新排列元素。
  • 重绘:
    • 当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘。
  • 直接合成阶段:
    • 更改一个既不要布局也不要绘制的属性,渲染引擎将跳过布局和绘制,只执行后续的合成操作,这个过程叫做合成;

2. 哪些实际操作会导致回流与重绘

  • 重排:
    • 页面初始渲染,这是开销最大的一次重排
    • 添加/删除可见的DOM元素
    • 改变元素位置
    • 改变元素尺寸,比如边距、填充、边框、宽度和高度等
    • 改变元素内容,比如文字数量,图片大小等
    • 改变元素字体大小
    • 改变浏览器窗口尺寸,比如resize事件发生时
    • 激活CSS伪类(例如::hover
    • 设置 style 属性的值,因为通过设置style属性改变结点样式的话,每一次设置都会触发一次reflow
  • 重绘:
    • 修改color
    • 修改border-style、border-radius

3. “重排”“重绘”和“合成”哪一个开销最大

相较于重排操作,重绘省去了布局和分层阶段,所以执行效率会比重排操作要高一些。

合成是在在非主线程上合成,并没有占用主线程的资源,另外也避开了布局和绘制两个子阶段,所以相对于重绘和重排,合成能大大提升绘制效率。

4 如何规避回流与重绘

  • js中样式集中改变,避免逐条改变样式,使用类名去合并样式

    // bad
    var left = 10;
    var top = 10;
    el.style.left = left + "px";
    el.style.top = top + "px";
    ​
    // 当top和left的值是动态计算而成时...
    // better 
    el.style.cssText += "; left: " + left + "px; top: " + top + "px;";
    // better
    el.className += " className";
    
  • 分离读写操作,DOM 的多个读操作(或多个写操作),应该放在一起。不要两个读操作之间,加入一个写操作。

    浏览器的渲染队列机制:

    当我们修改了元素的几何属性,导致浏览器触发重排或重绘时。

    它会把该操作放进渲染队列,等到队列中的操作到了一定的数量或者到了一定的时间间隔时,浏览器就会批量执行这些操作。

    // bad 强制刷新 触发四次重排+重绘
    div.style.left = div.offsetLeft + 1 + 'px';
    div.style.top = div.offsetTop + 1 + 'px';
    div.style.right = div.offsetRight + 1 + 'px';
    div.style.bottom = div.offsetBottom + 1 + 'px';
    ​
    ​
    // good 缓存布局信息 相当于读写分离 触发一次重排+重绘
    var curLeft = div.offsetLeft;
    var curTop = div.offsetTop;
    var curRight = div.offsetRight;
    var curBottom = div.offsetBottom;div.style.left = curLeft + 1 + 'px';
    div.style.top = curTop + 1 + 'px';
    div.style.right = curRight + 1 + 'px';
    div.style.bottom = curBottom + 1 + 'px';
    
  • 将 DOM 离线

    • 给元素设置 display:none ,添加足够多的变更后,通过 display属性显示。通过这种方式即使大量变更也只触发两次重排。
    • 通过 documentFragment创建一个 dom 碎片,在它上面批量操作 dom,操作完成之后,再添加到文档中,这样只会触发一次重排。

5. 如何在浏览器中查看页面渲染时间

打开开发者工具:点击 Performance 左侧有个小圆点 点击刷新页面会录制整个页面加载出来 时间的分配情况。

  • 蓝色: 网络通信和HTML解析
  • 黄色: JavaScript执行
  • 紫色: 样式计算和布局,即重排
  • 绿色: 重绘

哪种色块比较多,就说明性能耗费在那里。色块越长,问题越大

tool1.png