关于浏览器:重绘及回流

7次阅读

共计 1903 个字符,预计需要花费 5 分钟才能阅读完成。

浏览器的渲染过程

  1. 解析 HTML,生成 DOM 树,解析 CSS,生成 CSSOM 树
  2. 将 DOM 树和 CSSOM 树联合,生成渲染树(Render Tree)
  3. Layout(回流): 依据生成的渲染树,进行回流(Layout),失去节点的几何信息(地位,大小)
  4. Painting(重绘): 依据渲染树以及回流失去的几何信息,失去节点的相对像素
  5. Display: 将像素发送给 GPU,展现在页面上。

为了构建渲染树,浏览器次要实现了以下工作:

  1. 从 DOM 树的根节点开始遍历每个可见节点。
  2. 对于每个可见的节点,找到 CSSOM 树中对应的规定,并利用它们。
  3. 依据每个可见节点以及其对应的款式,组合生成渲染树。

第一步中,既然说到了要遍历可见的节点,那么咱们得先晓得,什么节点是不可见的。不可见的节点包含:

  1. 一些不会渲染输入的节点,比方 script、meta、link 等。
  2. 一些通过 css 进行暗藏的节点。比方 display:none。留神,利用 visibility 和 opacity 暗藏的节点,还是会显示在渲染树上的。只有 display:none 的节点才不会显示在渲染树上。

回流

后面咱们通过结构渲染树,咱们将可见 DOM 节点以及它对应的款式联合起来,可是咱们还须要计算它们在设施视口 (viewport) 内的确切地位和大小,这个计算的阶段就是回流。

重绘

最终,咱们通过结构渲染树和回流阶段,咱们晓得了哪些节点是可见的,以及可见节点的款式和具体的几何信息(地位、大小),那么咱们就能够将渲染树的每个节点都转换为屏幕上的理论像素,这个阶段就叫做重绘节点。

何时产生回流

回流这一阶段次要是计算节点的地位和几何信息,那么当页面布局和几何信息发生变化的时候,就须要回流。比方以下状况:

  1. 增加或删除可见的 DOM 元素
  2. 元素的地位发生变化
  3. 元素的尺寸发生变化(包含外边距、内边框、边框大小、高度和宽度等)
  4. 内容发生变化,比方文本变动或图片被另一个不同尺寸的图片所代替。
  5. 页面一开始渲染的时候(这必定防止不了)
  6. 浏览器的窗口尺寸变动(因为回流是依据视口的大小来计算元素的地位和大小的)

浏览器的优化机制

古代的浏览器都是很聪慧的,因为每次重排都会造成额定的计算耗费,因而大多数浏览器都会通过队列化批改并批量执行来优化重排过程。浏览器会将批改操作放入到队列里,直到过了一段时间或者操作达到了一个阈值,才清空队列。然而!当你获取布局信息的操作的时候,会强制队列刷新,比方当你拜访以下属性或者应用以下办法:

  1. offsetTop、offsetLeft、offsetWidth、offsetHeight
  2. scrollTop、scrollLeft、scrollWidth、scrollHeight
  3. clientTop、clientLeft、clientWidth、clientHeight
  4. getComputedStyle()
  5. getBoundingClientRect

缩小重绘与回流

CSS

  1. 应用 transform 代替 top
  2. 应用 visibility 替换 display: none,因为前者只会引起重绘,后者会引发回流(扭转了布局
  3. 防止应用 table 布局,可能很小的一个小改变会造成整个 table 的从新布局。
  4. 尽可能在 DOM 树的最末端扭转 class,回流是不可避免的,但能够缩小其影响。尽可能在 DOM 树的最末端扭转 class,能够限度了回流的范畴,使其影响尽可能少的节点。
  5. 防止设置多层内联款式,CSS 选择符从右往左匹配查找,防止节点层级过多。
  6. 将动画成果利用到 position 属性为 absolute 或 fixed 的元素上,防止影响其余元素的布局,这样只是一个重绘,而不是回流,同时,管制动画速度能够抉择 requestAnimationFrame,详见探讨 requestAnimationFrame。
  7. 防止应用 CSS 表达式,可能会引发回流。
  8. 将频繁重绘或者回流的节点设置为图层,图层可能阻止该节点的渲染行为影响别的节点,例如 will-change、video、iframe 等标签,浏览器会主动将该节点变为图层。
  9. CSS3 硬件加速(GPU 减速),应用 css3 硬件加速,能够让 transform、opacity、filters 这些动画不会引起回流重绘。

    JavaScript

  10. 防止频繁操作款式,最好一次性重写 style 属性,或者将款式列表定义为 class 并一次性更改 class 属性。
  11. 防止频繁操作 DOM,创立一个 documentFragment,在它下面利用所有 DOM 操作,最初再把它增加到文档中。
  12. 防止频繁读取会引发回流 / 重绘的属性,如果的确须要屡次应用,就用一个变量缓存起来。
  13. 对具备简单动画的元素应用相对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。
正文完
 0