什么是重绘:
当一个元素的样式外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘。
什么是回流:
当渲染树中的一部分或全部因为元素的规模尺寸、布局、隐藏等改变而需要重新构建,就叫做回流(重排)。
总结:回流必将引起重绘,而重绘不一定会引起回流。
常见的引起重绘的属性:
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()
什么情况下会触发重绘:
- 颜色修改
- 设置圆角
- 设置下划线
- 阴影修改
什么情况下会触发回流:
- 添加/删除DOM元素
- 元素位置发生变化
- 元素尺寸发生变化
- 内容发生变化,比如文本被图片替代
- 浏览器窗口尺寸变化
浏览器优化机制:
- 由于每次重排都会造成额外的计算消耗,因此大多数浏览器都会通过队列化修改并批量执行来优化重排过程。浏览器会将修改操作放入到队列里,直到过了一段时间或者操作达到了一个阈值,才清空队列。
- 当你获取布局信息的操作的时候,会强制队列刷新,触发回流重绘来返回最新的值。
如何优化或减少回流和重绘:
- 样式集中改变(cssText/className)
- 如果需要创建多个dom节点,可以使用 DocumentFragment 批量创建完成后一次性加入 document
- 将需要多次重排的元素,position 属性设为 absolute 或 fixed ,脱离文档流的元素发生变化时不会影响到其他元素
- 先设置元素为display:none;然后进行页面布局等操作;设置完成后将元素设置为 display:block;这样的话就只引发两次重绘和重排
- 使用 cloneNode(true or false) 和 replaceChild 技术,引发一次回流和重绘
- 尽量不要使用 table 布局,一个小的改动可能会使整个 table 进行重新
- 操作DOM时,尽量在底层级的DOM节点进行操作
- 使用transform实现动画,代替top/left