概念
我们已经了解过一次完整的http事务究竟是什么样子的了,其中最接近用户的操作大概就是浏览器解析html文件,因此下面就讲一下浏览器解析的大概工作流程:
从图中可以看到是四个步骤:
- 解析HTML,构建DOM树:浏览器中的渲染引擎负责解析html文档,转换树中的html标签或js生成的标签到DOM节点上,此为内容树
- 构建渲染树:解析CSS,根据CSS选择器计算出节点的样式,创建渲染书
- 布局渲染树:从根节点递归调用,计算每一个元素的大小位置等,给每一个节点所应该出现在屏幕上的精确坐标。
- 绘制渲染树:遍历渲染树,每个节点将使用UI后端层来绘制。
其中,Reapint和Reflow出现在了第三第四步,可以大概看出来这两步都发生了什么:
- Reflow时,浏览器根据样式来计算,根据计算结果将元素放在它该出现的位置。
- Repaint时,每个元素的位置的大小和位置以及其他一些属性都确定下来以后,浏览器按照这些元素的额各自特性绘制一次。
优化
所以,这两个步骤都是整个渲染过程不可或缺的部分,我们平时口中所说的页面渲染,其实可以只发生Repaint或者Reflow也可以两个都发生,例如说以下的一些操作:
- 对DOM节点进行增加删除修改时。
- 移动DOM节点的位置时。
- 修改DOM节点的CSS样式时
- 修改网页默认字体时
而在这里不得不提一下,Reflow的成本会比Repaint的高很多,因为一个节点reflow很可能会导致父节点或者同级节点的reflow,因为reflow时计算元素应该出现的位置并且把他们放在应该出现的位置。所以大量的reflow操作是需要尽量避免的,尽量将reflow对性能的影响减到最低。
- js修改DOM节点样式时,不要一个属性一个属性的修改。优化方法:先定义好css的class,然后修改className
|
|
- 不要把DOM节点的属性读写放在循环里,不然会大量读写该节点的属性
- 必须修改时,修改层级较低的DOM节点。
- 避免使用table布局,不然一个很小的改动会造成整个table的布局
- 把对象隐藏时,尽量使用
visibility: hidden;
代替display: none;
因为前者只触发了repaint后者触发了reflow和repaint 把DOM节点离线后修改:
- 使用documentFragment对象在内存里操作DOM
- clone一个DOM节点到内存里,然后对他进行修改,改完以后跟在线的那个DOM节点交换。
- 可以先 visibility: hiidden掉一个DOM节点,然后改完以后再显示出来。