要了解回流和重绘,先要知道一个网页的生成过程

网页生成过程 (网页渲染阶段)

从上面这个流程我们可以看出

  • reflow一定会引起repain
  • repaint不一定会引起reflow

    • reflow的性能消耗会大于repaint

      reflow & repaint 是什么

      reflow 回流 / 重排

      重新计算布局信息(因为节点的尺寸、布局、display:none block 这一些改变的时候),渲染树中的一部分或者全部需要重新构建(所以回流一定会引起重绘)

      repaint 重绘

      当前一个元素的外观发生改变,但其布局信息没有发生变化的重新绘制过程 (重绘不一定是回流产生的后续反应)

      引起回流的因素

  • 添加或者删除可见的 DOM 元素;

  • DOM 节点位置变化
  • 元素的尺寸、边距、填充、边框、宽高
  • DOM 节点 display 显示与否
  • 页面渲染初始化
  • 浏览器窗口尺寸变化 resize
  • 设置元素的style属性
  • 向浏览器请求某些样式信息
    • offset / scroll / client / width / height
    • getComputedStyle() / currentStyle()

      回流的性能代价比重绘高得多 因此写 DOM 要考虑回流的次数问题,以及回流时影响的节点数的规模问题

浏览器的队列策略

浏览器优化策略,把多次引起回流的操作,加入到一个队列中,在累积到一定数量或时间后,执行一次回流。批量合并为一次,减少回流次数。
但对于对浏览器请示某些样式信息时,浏览器会强制刷新队列。
点击查看【codepen】
此案例中就是利用 void h1.offsetWidth 来请求 H1 的 offsetWidth 强制刷新
void 是一个运算符,确保返回都是为 undefined

优化

目的是减少回流次数与规模,使用 GPU 处理动画

  1. 能不操作 DOM,尽量不操作 DOM。使用 CSS 样式直接加类名
  2. 对于不确定的样式值,使用style.cssText一次性更改
  3. 使用 doument.createDocumentFragment 文档碎片
  4. 使用 display: none,先隐藏 DOM,对style操作完成后再 display: block。
    1. 这样只产生两次回流
  5. 减少请求样式信息
    1. offset client scroll width heght getComputedStyle / currentStyle,如果不是动态每次都要获取时,使用时先用变量缓存
  6. 动画元素一定要绝对定位 position: absolute 新的图层,一般不超过 30 个
  7. 尽量不使用 table 布局
  8. 使用 CSS3 transform,使用 GPU