先看看浏览器是如何渲染网页的 
从图中可以看到,网页的渲染是分为两个部分的,HTML和CSS
- 解析HTML生成dom树、解析CSS生成样式规则
- 合成dom树和样式,形成渲染树
- 渲染树回流(Layout),再生成渲染树,渲染好之后重绘
- 最后展示在浏览器上
从图中还能得出一个结论: 回流必引起重绘
回流
通过构造render树,把dom节点和对应的css样式结合起来,但是浏览器还需要计算设备窗口大小,dom该如何展示,这个阶段叫做回流
重绘
最终,我们通过构造渲染树和回流阶段,我们知道了哪些节点是可见的,以及可见节点的样式和具体的几何信息(位置、大小),那么我们就可以将渲染树的每个节点都转换为屏幕上的实际像素,这个阶段就叫做重绘节点。
何时发生回流重绘
回流这一阶段主要是计算节点的位置和几何信息,那么当页面布局和几何信息发生变化的时候,就需要回流。比如以下情况
- 添加或删除dom元素
- 元素位置发生改变
- 元素尺寸发生变化
- 页面刚渲染时
- 浏览器窗口大小变化
浏览器的优化机制
现代浏览器的优化思想跟react、vue类似,批量渲染,把一系列的更新放在队列里面,当达到一定的阈值后,更新并清空队列。 这时候有个问题了,我们使用JS获取dom节点信息岂不是不准了? 所以浏览器有个强制回流机制,也就是当我们获取dom节点信息时,浏览器为了返回最新的dom节点信息给我们,不得不强行回流 比如使用这些方法:
- offsetTop
- scrollTop
- clientTop
- getComputedStyle()
- getBoudingClienRect()
- …
所以,使用这些方法时,尽量把值缓存下来,这样也是优化性能的做法
如何更优的渲染网页呢?
如果我们频繁修改dom,可以这样优化:
- 使dom脱离文档流
- 修改dom
- 把dom加入文档流
1、3步骤会造成回流,但是由于脱离了文档流, 修改dom不会造成回流了 脱离文档流的方法:
- 隐藏dom (display:none)
- 绝对定位
- 把dom拷贝到到一个脱离网页的节点中
复杂动画,使用绝对定位
css3硬件加速
比起考虑如何减少回流重绘,我们更期望的是,根本不要回流重绘。这个时候,css3硬件加速就闪亮登场了 常见的触发硬件加速的css属性:
- transform
- opacity
- filters
- Will-change