返回 blog
2021年1月25日
1 分钟阅读

重绘 回流

先看看浏览器是如何渲染网页的

从图中可以看到,网页的渲染是分为两个部分的,HTML和CSS

  1. 解析HTML生成dom树、解析CSS生成样式规则
  2. 合成dom树和样式,形成渲染树
  3. 渲染树回流(Layout),再生成渲染树,渲染好之后重绘
  4. 最后展示在浏览器上

从图中还能得出一个结论: 回流必引起重绘

回流

通过构造render树,把dom节点和对应的css样式结合起来,但是浏览器还需要计算设备窗口大小,dom该如何展示,这个阶段叫做回流

重绘

最终,我们通过构造渲染树和回流阶段,我们知道了哪些节点是可见的,以及可见节点的样式和具体的几何信息(位置、大小),那么我们就可以将渲染树的每个节点都转换为屏幕上的实际像素,这个阶段就叫做重绘节点。

何时发生回流重绘

回流这一阶段主要是计算节点的位置和几何信息,那么当页面布局和几何信息发生变化的时候,就需要回流。比如以下情况

  • 添加或删除dom元素
  • 元素位置发生改变
  • 元素尺寸发生变化
  • 页面刚渲染时
  • 浏览器窗口大小变化

浏览器的优化机制

现代浏览器的优化思想跟react、vue类似,批量渲染,把一系列的更新放在队列里面,当达到一定的阈值后,更新并清空队列。 这时候有个问题了,我们使用JS获取dom节点信息岂不是不准了? 所以浏览器有个强制回流机制,也就是当我们获取dom节点信息时,浏览器为了返回最新的dom节点信息给我们,不得不强行回流 比如使用这些方法:

  • offsetTop
  • scrollTop
  • clientTop
  • getComputedStyle()
  • getBoudingClienRect()

所以,使用这些方法时,尽量把值缓存下来,这样也是优化性能的做法

如何更优的渲染网页呢?

如果我们频繁修改dom,可以这样优化:
  1. 使dom脱离文档流
  2. 修改dom
  3. 把dom加入文档流

1、3步骤会造成回流,但是由于脱离了文档流, 修改dom不会造成回流了 脱离文档流的方法:

  1. 隐藏dom (display:none)
  2. 绝对定位
  3. 把dom拷贝到到一个脱离网页的节点中
复杂动画,使用绝对定位
css3硬件加速

比起考虑如何减少回流重绘,我们更期望的是,根本不要回流重绘。这个时候,css3硬件加速就闪亮登场了 常见的触发硬件加速的css属性:

  • transform
  • opacity
  • filters
  • Will-change