关于性能优化:reflow和repaint

一、reflow和repaint的定义

reflow(回流):只要增删DOM节点或修改元素的形状、大小,就会触发reflow。
repaint(重绘):只要元素样式属性(除形状、大小)发生改变了,就会触发repaint。

二、浏览器解析过程

image


1、解析HTML以构建DOM树

渲染引擎开始解析HTML文档,转换HTML标签到DOM节点,转换出来的产物叫DOM树。
DOM树的长相

2、解析CSS以构建CSSOM树

排版引擎开始解析CSS选择器,把CSS选择器集合解析成一个CSS对象模型(也称CSSOM树)。

解释:为什么DOM树和CSSOM树要分开解析生成呢?因为与DOM交互会很慢,所以我们用CSS自己本身去建了另一个树CSSOM,但是最终CSS的样式还是要映射在DOM树上起作用。

3、布局渲染树

从根节点递归调用,计算每一个元素的位置、大小,给每个节点精确坐标(指的是在屏幕上的精确坐标)。

4、绘制渲染树

在绘制阶段,系统会遍历渲染树,将其内容显示在屏幕上。


三、哪些情况会导致回流(reflow)


1、页面首次渲染

2、浏览器窗口大小发生改变

3、元素位置改变

4、元素尺寸改变

5、DOM元素的增删

6、激活CSS伪类(:hover)


四、reflow和repaint的优化


1、使用visibility: hidden替换display: none

display:显示/隐藏,显示时占据空间,隐藏时元素不占据空间。隐藏前后DOM结构有发生变化,需要重新渲染(reflow)。
visibility:显示/隐藏,显示时占据空间,隐藏时元素也占据空间。隐藏前后DOM结构未发生变化,不需要重新渲染(repaint)。

2、使用transform替换top、left、bottom、right

top、left、bottom、right:这几个属性是直接改变元素真实位置的,例如你设置了top: 5px; 那么元素就真的距离相对元素的顶部5px(reflow)。
transform:这个属性只是在视觉上改变了元素的位置,元素的真实位置并没有改变,例如你设置了 transform: translateY(5px); 元素其实还是在原本的位置上,只是相对于原来的位置向下偏移了5px(repaint)。

3、避免使用table布局

不要使用table布局,因为table需要遍历很多次,很小的一个改动会造成整个table的重新布局。

4、限制reflow的范围

例如:
(1) 在DOM树的最末端改变class
(2) 使用table时,设置table-layout: auto/fixed,这样table可以一行一行地渲染

这些行为都可以限制reflow的影响范围。

5、将动画效果应用到position属性为absolute或fixed的元素上

这样做动画效果将不影响其他元素的布局,这样做只会导致重绘(repaint),而不会导致一个完整回流(reflow),从而使性能消耗降低。

6、将频繁重绘或者回流的节点设置为图层

图层能够阻止该节点的渲染行为影响别的节点。
例如:video、iframe等标签以及will-change属性可以将元素变为图层。

其他的一些方法也可以对重绘和回流进行一些优化,但是我认为有些属性是必加的,有些方法是必须要那么使用的。不能为了优化重绘和回流而放弃一些必要的东西。
例如,避免使用CSS表达式可以减少回流,但是我们很多情况下需要用CSS表达式,尤其是类似弹框模块或者是一些运营页。

好的代码不一定是全方位的,也可能是有取舍的,在某方面好,可能会在另一方面有缺陷。

比如耦合逻辑减少了,但性能可能会有下降;代码简洁直观了,但接口(调用者)可能会觉得没以前好用,开发成本变高了。

取舍要结合具体场景,来衡量哪边是更重要的。




你可能感兴趣的:(关于性能优化:reflow和repaint)