前段时间有人我问过我重排 (Reflow) 与重绘 (Repaint) 的问题,这里写一篇文章描述一下重排与重绘的区别与优化手段,加深理解。
Firefox、Chrome 和 Safari 是基于两种渲染引擎构建的,Firefox 使用 Geoko——Mozilla 自主研发的渲染引擎,Safari 和 Chrome 都使用 webkit。
我们参考 webkit 的渲染流程:
先科普一下 HTML DOM:
HTML DOM,HTML Document Object Model(HTML 文档对象模型)的缩写,HTML DOM 定义了访问和操作 HTML 文档的标准。
W3C 对 HTML DOM 的解释:
1.HTML 的标准对象模型
2.HTML 的标准编程接口
3.W3C 标准
HTML DOM 定义了所有 HTML 元素的对象和属性,以及访问它们的方法。
换言之,HTML DOM 是关于如何获取、修改、添加或删除 HTML 元素的标准。
解释:
HTML->HTML Parser -> DOM Tree: 解析 html,创建 DOM Tree,即浏览器将 HTML 解析成树形的数据结构。
Style->CSS Parser->Style Rules: 解析 css,创建样式规则,其实也是将 css 解析成树形的数据结构。
Attachment->Render Tree->layout: 连接 DOM 节点与 CSS Rules 以构生成 Render Tree,在 render 树的基础上进行布局, 计算每个节点的几何结构,这里发生的就是重排(Reflow)。
painting->Display: 绘制,按照算出来的规则绘制样式,显示内容。
Reflow:当涉及到 DOM 节点的布局属性发生变化时,就会重新计算该属性,浏览器会重新描绘相应的元素,此过程叫 回流(Reflow)。
Repaint:当影响 DOM 元素可见性的属性发生变化 (如 color) 时, 浏览器会重新描绘相应的元素, 此过程称为 重绘(Repaint)。因此重排会引起重绘。
浏览器在处理重排时,会递归处理 DOM 节点,所以导致重排的成本高于重绘,我们只需避免重排即可,引起重排的操作:
1. 调整窗口大小
2. 字体大小
3. 样式表变动
4. 元素内容变化,尤其是输入控件
5.CSS 伪类激活(:hover、:active 等等),在用户交互过程中发生
6.DOM 操作,DOM 元素增删、修改
7.width, clientWidth, scrollTop 等布局宽高的计算
这么看,我们只要避免两种操作即可达到性能优化:
1. 避免大量的 DOM 操作
2. 避免过多 DOM 布局属性的计算
细分:
1. 不要直接读取 style 属性逐条修改保存。应该集中修改样式,譬如直接修改 className。2. 创建 div,设置 display:none,然后将它所有的 DOM 操作全部应用上,最后再添加到 html 文档里,修改 display,显示出来。3. 避免频繁读取元素几何属性(例如 scrollTop)。4. 绝对定位具有复杂动画的元素。绝对定位使它脱离文档流,避免引起父元素及后续元素大量的回流。
后面了解到更多时,再补充。