重流和重绘在性能优化中是相当重要的,在这里需要将其记录下来。首先了解渲染引擎。
渲染引擎
渲染引擎需要负责显示请求的内容。如果请求的内容是HTML,它就负责解析HTML 和CSS 内容,并将解析后的内容显示在屏幕上。
渲染引擎的种类
1.FireFox:Gecko 引擎
2.Safari:WebKit 引擎
3.Chrome: Blink 引擎
4.IE:Trident 引擎
5.Edge:EdgeHTML 引擎
渲染引擎处理网页的过程
WebKit 主流程
Mozilla 的Gecko 渲染引擎主流程
1.解析代码:HTML 代码解析为DOM,CSS 代码解析为CSSOM(CSS Object Model)。
2.对象合成:将DOM 和CSSOM 合成一棵渲染树(render tree)。
3.布局:计算出渲染树的布局(layout)
4.绘制:将渲染树绘制到屏幕。
以上四步并非严格按顺序执行,往往第一步还没完成,第二步和第三步就就已经开始了。所以,会看到这种情况:网页的HTML 代码还没下载完,但浏览器已经显示出内容了。
重流和重绘
渲染树转换为网页布局,称为“布局流”(flow);布局显示到页面的这个过程,称为“绘制”(paint)。它们都具有阻塞效应,并且会消耗很多时间和计算资源。
页面生成以后,脚本操作和样式表操作,都会触发“重流”(reflow)和“重绘”(repaint)。用户的互动也会触发重流和重绘,比如设置了鼠标悬停(a:hover
)效果、页面滚动、在输入框中输入文本、改变窗口大小等等。
重流和重绘不一定一起发生,重流必然导致重绘,重绘不一定需要重流。比如改变元素颜色,只会导致重绘,而不会导致重流;改变元素的布局,则会导致重绘和重流。
大多数情况下,浏览器会智能判断,将重流和重绘只限制到相关的子树上,最小化所耗费的代价,而不会全局重新生成网页。例如:元素的颜色改变后,只会对该元素进行重绘。元素位置改变后,只会对该元素及其子元素(可能还有统计元素)进行布局和重绘。添加DOM 节点后,会对该节点进行布局和重绘。一些重大变化(例如增加<html>
元素的字体)会导致缓存无效,使得整个呈现树都会进行重新布局和绘制。
性能优化
作为开发者,应该尽量设法降低重绘的次数和成本。比如,尽量不要变动高层的DOM 元素,而以底层DOM 元素的变动代替;再比如,重绘table
布局和flex
布局,开销都比较大。
优化技巧
1.读取DOM 或者写入DOM,尽量写在一起,不要混杂。不要读取一个DOM 节点,然后立刻写入,接着再读取一个DOM 节点。
2.缓存DOM 信息。
3.不要一项一项地改变样式,而是使用CSS class 一次性改变样式。
4.使用documentFragment
操作DOM。
5.动画使用absolute
定位或fixed
定位,这样可以减少对其他元素的影响。
6.只在必要时才显示隐藏元素。
7.使用window.requestAnimationFrame()
,因为它可以把代码推迟到下一次重流时执行,而不是立即要求页面重流。
8.使用虚拟DOM(virtual DOM)库。