赞
踩
首先,我们需要先明白一个问题
下面是网上的一张图片,可以很清晰的说明前三步
布局阶段会从渲染树的根节点开始遍历,然后确定每个节点对象在页面上的确切的大小和位置,所有相对的测量值也都会被转换为屏幕内的绝对像素值。
浏览器主进程将默认的图层(普通文档流的元素)和多个独立图层交给GPU进程,GPU进程再将各个图层合成,最终显示在屏幕上。
哪些元素会独立图层?<video><iframe><canvas>
等。
下面是一张网站的图层图片,可见,所有元素并不是都在一个图层上展示。
理解了网页渲染页面的过程,也明白了图层,下面来看一下什么是回流?什么是重绘?
当渲染树中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就叫称为重绘。
Color
Border-style
Border-radius
Visibility
Text-decoration
Background
Background-img
Outline-color
Box-shadow
……
当渲染树中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为回流。每个页面至少需要一次回流,就是在页面第一次加载的时候,这时候是一定会发生回流的,因为要构建渲染树。
引发问题:回流的代价要远高于重绘,回流会造成重绘,重绘不一定回流。回流浏览器需要重新渲染页面,从而影响性能。
width
Height
Padding
Margin
Display
Border-width
Border
width
Height
Padding
Margin
Display
Border-width
Border
width
Height
Padding
Margin
Display
Border-width
Border
我们既然明白了什么是重绘和回流,以及哪些因素和元素导致了回流和重绘,并且明白了重绘回流在页面渲染过程中造成哪些影响,那我们如何优化呢?
主要从下面两个方面来避免发生重绘回流
- 将频繁回流的DOM元素作为一个独立的图层,那么这个DOM元素的回流只影响这一个图层,其他图层不会受影响。
- 避免使用触发回流的css属性。
1. 多次改变DOM元素的属性,并不会像之前说的那样,引发多次回流重绘,而是将这些合并为一次,因为浏览器中有缓冲机制,通过这个缓冲机制,能够减少回流重绘的次数,比如控制在100ms周期内,多次回流重绘合并为一次,这属于浏览器自身的性能优化。
由上面结果可以看出,多次改变DOM的属性,并不会发生多次回流重绘,事实上,只导致了一次,但是我们还是要做自己代码的优化,尽量减少回流重绘的次数,我们不能让浏览器自身的机制来保证代码的性能,每个浏览器自身的优化性能也都不同,所以我们尽量使我们写出来的代码变得强壮。
2. 循环中获取offsetWidth
结果如下:回流发生了100次,也就是获取多少次offsetTop,就发生了多少次回流,并且根据下面的图片可以看出,已经报红色了,因为这其中进行了100次的强制性回流,事实上,获取offsetTop这个属性的时候,已经不再遵循上面讲的浏览器自身性能优化的规律了,获取一次,会留一次。
为什么会导致这个问题呢?
因为我们在读取元素offsetTop之前,先在该元素中添加了一个新的元素,浏览器为了给我们最新的offsetTop值,需要重新布局来获取。
如果在获取值之前,不对该元素进行写的操作,会怎样呢?
事实上,读写分离后,值发生了一次回流。
抛开读写分离这件事,那上面的例子我们应该如何优化呢,可以将获取的offsetTop的值取出来之后作为缓存,不要每次循环都获取。
对于这个例子,也有人说,是因为每次循环中都需要读写DOM元素导致的性能降低,JS每次都读写DOM元素无疑会大大降低性能,但不会发生回流。
3. 合理利用GPU硬件加速
在做各种前端动画实现时,充分利用GPU加速,可以使动画更加流畅,用户体验更好,利用GPU这种硬件层次的加速,我们永远不用担心会触及它的上限,因为在触及上限前,一定先会触发浏览器的上限。
一些css3的属性会触发GPU加速:
上述的几大效果都会触发浏览器的GPU加速机制。在做动画时,尽量通过css3的动画代替传统的定时器轮询,用改变top/left/width/height值得方式来完成动画的渲染。这样既可以做出优美的动画,也不会对渲染性能造成影响。
4.将频繁引发页面回流的元素独立图层
重绘和回流对页面渲染期间的性能影响很大,动画的元素会频繁的触发页面的回流,为了减少动画元素对其他元素的影响,从而减少页面重绘回流的次数,我们需要将动画元素提升为独立层。
动画会频繁触发回流和重绘
独立图层后不再发生回流
对于类似动画元素这种频繁引发页面回流重绘的元素来说,独立出来一个图层是能更好的提高渲染方面的性能,但是创建一个图层并不是免费的,它需要消耗额外的内存和管理资源。在内存资源有限的设备上,合成层带来的性能改善,可能远远赶不上过多合成层开销给页面性能带来的负面影响。比如一些较旧的手机和电脑,开启加速,无论是电池还是发热量都会比平时高。
同时,由于每个渲染层的纹理都需要上传到GPU处理,因此我们还需要考虑CPU和GPU之间的带宽问题,以及有多大内存供GPU处理这些纹理。
元素未独立图层
元素独立图层
以上文章为个人理解加上实践结果,如有理解不正确的地方,还请指正,感激不尽。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。