一. 首先要明确页面加载到完全渲染结束的过程,
浏览器是流式的布局模式,浏览器会将html解析成DOM,css解析成CSSOM,DOM和CSSOM会形成渲染树(renderTree),renderTree形成之后,浏览器能计算出各个节点在浏览器的位置,将节点渲染到浏览器上面
1.根据文档渲染DOM树,包括display:none的节点
2.在DOM树的基础上根据节点几何属性(margin/padding/width/height)生成render树,不包括display:none和head节点,但是包括visbility:hidden节点
3.在render树的基础上进一步渲染包括color,outline等样式
reflow:当render树中的一部分或者全部元素的规模尺寸,布局,隐藏等问题发生改变而需要重建的过程叫做回流
repaint:当元素的一部分属性发生变化,如外观背景色不会引起布局变化而需要重新渲染的过程叫做重绘
二. 哪些操作会引起回流?
1.dom树结构的变化,例如添加或删除某个节点
2.页面初始化渲染
3.节点几何属性的变化(width,height,margin,padding变化)
4.浏览器窗口发生-resize事件变化
5.获取某些属性,虽然浏览器会对回流做一些优化处理,比如Opera,它会等到有足够 数量的变化发生,或者等到一定的时间,或者等一个线程结束,再一起处理,这样就只发生一次重排。但除了render树的直接变化,当获取一些属性时,浏览器为取得 正确的值也会触发回流。这样就使得浏览器的优化失效了。这些属性包括offsettop,offsetleft,offsetwidth,offsetheight,scorllTop,scrollLeft,scrollWidth,scrollHeight,clientTop,clientLeft,clientWidth,clientHeight
三.有哪些优化的手段
1.对于多次使用到回流节点,使用absolute和fixed使节点脱离文档流,复杂动画一定要使用absolute或者fixed使得脱离文档流
2.改变样式的操作一次完成,修改一个class的name,其中包括了要修改的所有样式
3.将元素设置为display:visibility
,因为display:none会引起回流,而visibility
只会引起重绘
4.不要经常访问浏览器flush队列属性,即不要经常使用上面提到的offsetLeft等方法,如果确实需要多次使用,就用一个变量缓存起来
5.尽量不要使用表格,因为在没有确定一列表格宽度的时候,表格的每一列都会使用最大宽度的一列为标准渲染,如果最后渲染出来的表格宽度超过了页面的宽度,引起整体回流造成table可能需要多次计算才能确定好其在渲染树中节点的属性,通常要花3倍于同等元素的时间
6.避免重绘,避免使用CSS表达式(例如:calc()),避免设置多层内联样式
7.js操作中避免重复操作样式,一次性写好,避免频繁操作DOM
四.总结
回流一定伴随重绘,重绘不一定有回流,回流消耗的性能比重绘高的多