回流和重绘

js 收藏
0 32

一、什么是重绘?回流(重排)?

  • 回流:重新生成布局。因为节点的尺寸、布局、显示(display: none/block)改变这些属性改变的时候,渲染树中的一部分或者全部需要重新构建,这种重新构建的现象就是回流
  • 重绘:重新绘制。完成回流后,浏览器会重新绘制受影响的部分到屏幕中。这个过程称为重绘
回流一定会导致重绘,重绘不一定导致回流。如果DOM变化不影响几何属性,元素的布局没有改变,则只发生一次重绘(不需要回流)。

二. 引起回流的因素:

DOM节点增加、删除

DOM节点位置变化

元素的尺寸、边距、填充(文字、图片)、边框、宽高

DOM节点display显示与否,不包含visibility

页面渲染初始化(第一次加载页面)

浏览器窗口尺寸变化(resize)

向浏览器请求某些样式信息(offset、scroll、client、width/height、getComputedStyle、currentStyle)

除开以上几个因素以外只会引起重绘。

dom操作之所以消耗性能,就是因为容易引起回流,所以在做dom操作优化的时候就是以减少回流次数为依据来进行优化的,之所以需要缓存、文档碎片就是为了减少回流次数。

三. 如何减少重绘和回流

  1. CSS中避免回流、重绘

尽可能在DOM树的最末端改变class
避免设置多层内联样式
动画效果应用到position属性为absolute或fixed的元素上
避免使用table布局
使用css3硬件加速,可以让transform、opacity、filters等动画效果不会引起回流重绘

2. JS操作避免回流、重绘

避免使用JS一个样式修改完接着改下一个样式,最好一次性更改CSS样式,或者将样式列表定义为class的名称
避免频繁操作DOM,使用文档片段创建一个子树,然后再拷贝到文档中
先隐藏元素,进行修改后再显示该元素,因为display:none上的DOM操作不会引发回流和重绘
避免循环读取offsetLeft等属性,在循环之前把它们存起来
对于复杂动画效果,使用绝对定位让其脱离文档流,否则会引起父元素及后续元素大量的回流

当我们对DOM进行修改操作时,比如添加/删除节点、修改元素属性、调用了影响到元素布局的CSS属性等,都会导致浏览器进行回流来重新计算元素的位置和大小。这个过程可能会消耗大量的CPU资源,因此应该避免频繁地进行回流操作。

而重绘则是指只有元素外观上的改变,不涉及布局的情况下,浏览器依然会重新绘制元素以展现最新的样式效果。常见的引起重绘的原因包括修改文本内容、修改字体颜色、修改边框样式等。同样地,也应该尽量避免频繁地进行重绘操作。

为了提高网页性能,可以通过以下方法来减少回流和重绘次数:

  1. 使用classList API来管理类名,而非直接修改className属性;

  2. 将多个样式修改合并成一次修改,减少重绘次数;

  3. 使用transforms和opacity等特定的CSS属性来处理动画效果,避免频繁的回流和重绘;

  4. 使用requestAnimationFrame()函数来控制动画的渲染,从而减少回流和重绘的次数;

  5. 避免频繁地获取元素的offsetWidth、clientHeight等属性值,因为每次获取都会触发回流。

    暂时没有人评论