参考文章
https://blog.csdn.net/songlf521/article/details/115181445
浏览器渲染的过程
- 解析html生成dom树
- 解析css生成cssom树
- 将dom树和cssom树结合在一起,生成渲染树renderTree
- 根据渲染树,计算节点的位置和大小,这就是回流
- 根据渲染树,和回流得到的几何信息,计算节点的绝对像素值,这就是重绘
- 将像素发给GPU,展示在页面上
渲染树形成过程
- 从dom树的根节点开始遍历每个可见节点
- 每个可见节点找到cssom树对应的规则
- 根据可见节点和对应的规则,生成渲染树
可见节点
- 不可见节点,不会被渲染到渲染树里,比如script,meta,link,style
- display:none 的节点是不可见节点,不会被渲染到渲染树里
- visibility和opacity隐藏的节点,是会被渲染到渲染树里的,但是会被浏览器隐藏显示
回流
- 几何信息需要改变就是回流
- 一个元素的回流可能会导致所有子元素和随后节点和祖先节点的回流
什么时候发生回流
- 添加删除可见节点
- 位置和大小变化
- 最开始的渲染
- 浏览器窗口大小变化
重绘
- 样式需要改变就是重绘,比如outline,visibility,color,background-color
- 回流一定会发生重绘,重绘不一定会发生回流
- 回流的成本高于重绘
回流和重绘的优化方法
避免改变浏览器的优化机制
- 现代浏览器会将每次的回流和重绘放在一个队列中,进行批量执行来进行优化。但是有些操作会强制刷新队列:
offsetTop, offsetLeft, offsetWidth, offsetHeight, scrollTop, scrollLeft, scrollWidth, scrollHeight, clientTop, clientLeft, clientWidth, clientHeight, getComputedStyle(), getBoundingClientReact()
优化css修改方式
- 多个样式最好写在一块,一起修改
批量修改dom
- 多次添加元素,可以先将父元素display:none,等元素全部添加完成,再改为block
- 使用文档片段(document fragment),在当前dom之外构建一个子树,将其拷贝到文档
将元素脱离文档流,独立图层
- 一个图层的回流和重绘只会在当前图层,不会影响其他图层,可以将一些频繁渲染的放在独立涂层中,比如动画
- 会自动建立图层
transform,translate, transition,video元素, canvas
其他方式
- translate代替top,top会回流,translate不会
- opacity代替visibility,visibility会回流和重绘,opacity不会
- 不要使用table布局,它的很小改变都会回流和重绘,尽量使用div