渲染优化:重绘(Repaint)和回流(Reflow)
面试题
- 有没有了解过重绘与回流的概念吗?
- transform这个属性的偏移是回流还是重绘?
- 如果是transform:rotate进行了旋转是回流还是重绘?
- 什么时候会触发回流(重排)和重绘?
- 如何防止重绘重排:项目中的优化
什么是重绘和回流
- 回流(再次触发页面布局):渲染树中的元素改变了几何属性、布局等发生变化等需要重新计算节点的大小和位置。
- 重绘:当渲染树中元素样式发生改变且未影响其几何属性时,将重新绘制渲染树中节点到屏幕中。
回流必定会发生重绘,重绘不一定会引发回流。
重绘和回流的触发时机
回流
- DOM元素的几何属性发生变化
- 更改DOM树的结构
- 获取一些特定属性的值:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollxxx、clientxxx
- window.getComputedStyle(Dom Element)方法
原因:浏览器的优化机制
浏览器优化机制
由于每次回流都会造成额外的计算消耗,因此大多数浏览器都会通过队列化修改并批量执行来优化回流过程。浏览器会将修改操作放入到队列里,直到过了一段时间或者操作达到了一个阈值,才清空队列
当你获取布局信息的操作的时候,浏览器会清空队列,触发回流重绘来返回正确的值,所以会强制队列刷新。
优化方案
1. 使用GPU加速-本质合成阶段的优化
原理:跳过重绘和回流过程,直接到合成阶段。
合成阶段的作用是将已绘制的不同图层合并成在一起,输出到屏幕。
布局(回流)–>绘制(重绘)–>合成
在绘制中不同的图层渲染互不影响
开启GPU加速的办法
仅与合成相关的动画属性:transform
、opacity
会跳过布局和绘制阶段,新建图层交给GPU渲染。
GPU硬件加速是需要新建图层,将其提升到一个独立的图层,而把该元素移动到新图层是个耗时操作,使用will-change
属性提前告诉浏览器在开始就把元素放到新的图层,方便后面GPU渲染的时候,不需要做图层的新建。
2. JS优化
- 避免频繁改动使用
style
,采用修改class
的方式 - 对于 scroll 等事件进行防抖/节流处理。
- 使用变量缓存对敏感属性值(offset等)的计算