reflow(回流)与repaint(重绘)的区别及优化

1.回流及重绘的概念

回流(reflow):当render tree中的元素的宽高、布局、显示、隐藏或元素内部文字结结构发生改变时,会影响自身及其父元素、甚至追溯到更多的祖先元素发生改变,则会导致元素内部、周围甚至整个页面的重新渲染,页面发生重构,回流就产生了。

重绘(repaint):元素的结构(宽高、布局、显示隐藏、内部文字大小)未发生改变,只是元素的外观样式发生改变,比如背景颜色、内部文字颜色、边框颜色等。此时会引起浏览器重绘,显然重绘的速度快于回流。

回流一定会触发重绘,重绘不一定触发回流。

2.回流重绘对性能的影响

这里了解一个知识点:渲染css样式会影响js执行的时间,使得加载js脚本变慢。原因如下:

浏览器渲染一个网页的时候会启用两条线程:一条渲染javascript 脚本,另一条渲染 ui 即css 样式的渲染。但这两条线程是互斥的,当javascript 线程运行的时候 ui 线程则会中止暂停,反之亦然。因为当ui 线程运行对页面进行渲染的时候, js 脚本难免会涉及到页面视图上的一些样式的改变,为了使这个改变更加准确 js 脚本只好等待ui 线程渲染完成的时候才去执行。

所以当一个页面的元素样式改动频繁的时候ui 线程就会持续渲染,造成js 代码反应慢半拍,卡顿的情况。回流和重绘都会使得ui线程渲染时间加长,太多就会使得网站性能变差,因此要尽量减少reflow和repaint。

3.如何减少回流和重绘

 导致回流发生的情况如下:

  • 改变窗口大小
  • 改变文字大小
  • 内容的改变,如用户在输入框中敲字
  • 激活伪类,如:hover
  • 操作class属性
  • 脚本操作DOM
  • 计算offsetWidth和offsetHeight
  • 设置style属性

 对应的css属性如下:

  • 盒子模型相关属性
  • 定位及浮动属性
  • 节点内部的文字结构

  

 导致重绘的css属性如下:

  

 

  减少回流和重绘注意点如下:

1:用transform 代替 top,left ,margin-top, margin-left... 这些位移属性

2:用opacity 代替 visibility,但是要同时有translate3d 或 translateZ 这些可以创建的图层的属性存在才可以阻止回流

但是第二点经过我的实验,发现如果不加 transform: translateZ(0) 配合opacity的话还是会产生回流的,而只用visibility 就只会产生重绘不会回流

而  opacity 加上 transform: translateZ/3d  这个属性之后便不会发生回流和重绘了

3:不要使用 js 代码对dom 元素设置多条样式,选择用一个 className 代替之。

4:如果确实需要用 js 对 dom 设置多条样式那么可以将这个dom 先隐藏,然后再对其设置

5:不要在循环内获取dom 的样式例如:offsetWidth, offsetHeight, clientWidth, clientHeight... 这些。浏览器有一个回流的缓冲机制,即多个回流会保存在一个栈里面,当这个栈满了浏览器便会一次性触发所有样式的更改且刷新这个栈。但是如果你多次获取这些元素的实际样式,浏览器为了给你一个准确的答案便会不停刷新这个缓冲栈,导致页面回流增加。

所以为了避免这个问题,应该用一个变量保存在循环体外。

6:不要使用table 布局,因为table 的每一个行甚至每一个单元格的样式更新都会导致整个table 重新布局

7:动画的速度按照业务按需决定。

8:对于频繁变化的元素应该为其加一个 transform 属性,对于视频使用video 标签

9:必要时可以开启 GPU 加速,但是不能滥用

相关参考:

https://www.cnblogs.com/zhutao/p/6551216.html

https://www.cnblogs.com/stitchgogo/p/7920828.html

posted @ 2019-10-18 12:30  半忧夏  阅读(1918)  评论(0编辑  收藏  举报