重绘与回流

52 阅读2分钟

什么是重绘:

当一个元素的样式外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘。

什么是回流:

当渲染树中的一部分或全部因为元素的规模尺寸、布局、隐藏等改变而需要重新构建,就叫做回流(重排)。

总结:回流必将引起重绘,而重绘不一定会引起回流。

常见的引起重绘的属性:

color、background、box-shadow、border-radius、border-style、outline(轮廓线)、text-decoration(下划线)

常见的引起回流的属性:

width、height、margin、pading、display、border-width、position、font-size、text-align、line-height、overflow、float、伪类(:hover)、getComputedStyle()、getBoundingClientRect()

什么情况下会触发重绘:

  1. 颜色修改
  2. 设置圆角
  3. 设置下划线
  4. 阴影修改

什么情况下会触发回流:

  1. 添加/删除DOM元素
  2. 元素位置发生变化
  3. 元素尺寸发生变化
  4. 内容发生变化,比如文本被图片替代
  5. 浏览器窗口尺寸变化

浏览器优化机制:

  1. 由于每次重排都会造成额外的计算消耗,因此大多数浏览器都会通过队列化修改并批量执行来优化重排过程。浏览器会将修改操作放入到队列里,直到过了一段时间或者操作达到了一个阈值,才清空队列。
  2. 当你获取布局信息的操作的时候,会强制队列刷新,触发回流重绘来返回最新的值。

如何优化或减少回流和重绘:

  1. 样式集中改变(cssText/className)
  2. 如果需要创建多个dom节点,可以使用 DocumentFragment 批量创建完成后一次性加入 document
  3. 将需要多次重排的元素,position 属性设为 absolute 或 fixed ,脱离文档流的元素发生变化时不会影响到其他元素
  4. 先设置元素为display:none;然后进行页面布局等操作;设置完成后将元素设置为 display:block;这样的话就只引发两次重绘和重排
  5. 使用 cloneNode(true or false) 和 replaceChild 技术,引发一次回流和重绘
  6. 尽量不要使用 table 布局,一个小的改动可能会使整个 table 进行重新
  7. 操作DOM时,尽量在底层级的DOM节点进行操作
  8. 使用transform实现动画,代替top/left