首先是HTML渲染过程
解析HTML并构建DOM树和CSSOM树,浏览器对HTML标记转换成文档对象模型,CSS标记则转换成CSS对象模型(CSSOM),DOM 树包含了所有的 html 标签,包括不展示的 head 节点和 display:none 的节点,而 CSSOM 树则会去掉浏览器不能识别的样式,比如不支持的浏览器前缀(chrome不支持的-moz-前缀)和 hack(如firefox不支持_开头的样式)
接着就是构建render 树。将 DOM 树和 CSSOM 树合并为 render 树,在这个过程中,需要计算每一个呈现对象的可视化属性,会去掉不展示在页面上的节点(如 display:none 和 head 节点等),因为这些节点不会用于呈现,而且不会影响呈现的,所以就不会包含到render tree中,但是visibility:hidden隐藏的元素还是会包含到render tree中的,因为visibility:hidden 会影响布局(layout),会占有空间。
然后是布局 render 树。render 树在创建完成时,并不包含位置和大小信息。计算这些值的过程称为布局或重排。从 render 树的根节点((对应于 HTML 文档的 元素))递归调用,计算每一个元素的位置和大小信息。
最后使用 render 树绘制页面。在绘制阶段,系统会遍历 render 树,将其内容显示在屏幕上。
那么什么是回流,什么又是重绘呢?
回流(Reflow):render 树中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程称为重绘。
重绘:render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响 render 树重新布局的,比如修改字体颜色
那么什么情况下会产生回流呢?
1. 改变 DOM 树结构,比如添加或者删除可见的元素、改变文本内容、改变位置
2. 改变元素几何尺寸:边距、填充、边框、宽度和高度
3. 改变浏览器窗口尺寸
4. 伪类激活,在用户交互过程中发生
应该尽量减少回流和重绘,那么怎样优化浏览器渲染过程?
其实优化就是减少对render tree的操作,并减少对一些style信息的请求,尽量利用好浏览器的优化策略。
1. 不要1个1个改变元素的样式属性,最好直接改变className,但className是预先定义好的样式,不是动态的,如果你要动态改变一些样式,则使用cssText来改变
2. 让操作元素离线处理
即使用documentFragment或div等元素进行缓存操作,先把所有要添加到元素添加到1个div,最后才把这个div append到body中
先display:none 隐藏元素,然后对该元素进行所有的操作,最后再显示该元素。因对display:none的元素进行操作不会引起回流、重绘。
3. 将引起回流的属性赋值给变量,进行缓存,需要用到的时候直接使用变量就行
4. 减少操作影响的节点,影响的节点越多,则越消耗性能。
参考:https://github.com/tcatche/tcatche.github.io/issues/60