一、什么是重绘?回流(重排)?
回流一定会导致重绘,重绘不一定导致回流。如果DOM变化不影响几何属性,元素的布局没有改变,则只发生一次重绘(不需要回流)。
二. 引起回流的因素:
DOM节点增加、删除
DOM节点位置变化
元素的尺寸、边距、填充(文字、图片)、边框、宽高
DOM节点display显示与否,不包含visibility
页面渲染初始化(第一次加载页面)
浏览器窗口尺寸变化(resize)
向浏览器请求某些样式信息(offset、scroll、client、width/height、getComputedStyle、currentStyle)
除开以上几个因素以外只会引起重绘。
dom操作之所以消耗性能,就是因为容易引起回流,所以在做dom操作优化的时候就是以减少回流次数为依据来进行优化的,之所以需要缓存、文档碎片就是为了减少回流次数。
三. 如何减少重绘和回流
尽可能在DOM树的最末端改变class
避免设置多层内联样式
动画效果应用到position属性为absolute或fixed的元素上
避免使用table布局
使用css3硬件加速,可以让transform、opacity、filters等动画效果不会引起回流重绘
2. JS操作避免回流、重绘
避免使用JS一个样式修改完接着改下一个样式,最好一次性更改CSS样式,或者将样式列表定义为class的名称
避免频繁操作DOM,使用文档片段创建一个子树,然后再拷贝到文档中
先隐藏元素,进行修改后再显示该元素,因为display:none上的DOM操作不会引发回流和重绘
避免循环读取offsetLeft等属性,在循环之前把它们存起来
对于复杂动画效果,使用绝对定位让其脱离文档流,否则会引起父元素及后续元素大量的回流
当我们对DOM进行修改操作时,比如添加/删除节点、修改元素属性、调用了影响到元素布局的CSS属性等,都会导致浏览器进行回流来重新计算元素的位置和大小。这个过程可能会消耗大量的CPU资源,因此应该避免频繁地进行回流操作。
而重绘则是指只有元素外观上的改变,不涉及布局的情况下,浏览器依然会重新绘制元素以展现最新的样式效果。常见的引起重绘的原因包括修改文本内容、修改字体颜色、修改边框样式等。同样地,也应该尽量避免频繁地进行重绘操作。
为了提高网页性能,可以通过以下方法来减少回流和重绘次数:
使用classList API来管理类名,而非直接修改className属性;
将多个样式修改合并成一次修改,减少重绘次数;
使用transforms和opacity等特定的CSS属性来处理动画效果,避免频繁的回流和重绘;
使用requestAnimationFrame()函数来控制动画的渲染,从而减少回流和重绘的次数;
避免频繁地获取元素的offsetWidth、clientHeight等属性值,因为每次获取都会触发回流。