前端学习19 重排与重绘
在前端开发中,CSS性能对页面的加载速度和交互体验起着关键作用,其中重排(Reflow)和重绘(Repaint)机制是影响CSS性能的核心因素。深入理解并有效优化重排与重绘,能显著提升页面性能。在Vue使用环境下,重排和重绘有着独特的触发场景和优化策略。
1. 重排(reflow) 和 重绘(repaint)
重排:也叫回流,适当DOM的变化影响了元素的集合属性,如宽度、高度、位置、外边距、内边距、边框厚度等,浏览器需要重新计算元素的布局,并重新构建渲染树的过程。
重绘:当一个元素的外观发生变化,比如改变元素的 color 、 background - color 、 visibility 、 outline 等属性,但没有改变布局,重新把原始外观绘制出来的过程。
重排比重绘的开销更大,因为重排通常会导致重绘。当发生重排时,元素的几何属性改变,其外观也可能随之改变,所以在重排之后往往会进行重绘;而重绘不一定会导致重排,比如仅改变元素颜色,只涉及重绘,不会触发重排。
2. 浏览器渲染机制
- 解析HTML,生成DOM树,解析CSS,生成CSSOM树
- 将DOM树和CSSOM树结合,生成渲染树(Render Tree)
- Layout(回流):根据生成的渲染树,进行回流(Layout),得到节点的几何信息(位置,大小)
- Painting(重绘):根据渲染树以及回流得到的几何信息,得到节点的绝对像素
- Display:将像素发送给GPU,展示在页面上
在页面初始渲染阶段,回流不可避免的触发,可以理解成页面一开始是空白的元素,后面添加了新的元素使页面布局发生改变。
当我们对 DOM 的修改引发了 DOM几何尺寸的变化(比如修改元素的宽、高或隐藏元素等)时,浏览器需要重新计算元素的几何属性,然后再将计算的结果绘制出来。
3.优化策略
3.1 样式集中改变
不要频繁的操作样式,对于一个静态页面来说,明智且可维护的做法是更改类名,而不是修改样式。对于动态改变的样式来说,相较每次微小修改都直接触及元素,更好的办法是统一在cssText 变量中编辑。
let ulDom = document.getElementById(“box”); ulDom.style.left = “100px”; ulDom.style.top = “200px”; //最好改成如下(cssText): let ulDom = document.getElementById(“box”); ulDom.style.cssText = ‘left :100px;top:200px;’
3.2 分离读写操作
DOM的多个读操作或者写操作,应该放在一起,不要两个读操作之间加入一个写操作。
当我们修改了元素的集合属性,导致浏览器触发重排或重绘时,它会把该操作放进渲染队列,等到队列中操作到了一定的数量或者到了一定的时间间隔时,浏览器就会批量执行这些操作。
let ulDom = document.getElementById(“box”); var curLeft=ulDom .offsetLeft; var curTop=ulDom .offsetTop; ulDom .style.left=curLeft+1+'px'; ulDom .style.top=curTop+1+'px';
下面的写法是不好的:
let ulDom = document.getElementById(“box”); var curLeft=ulDom .offsetLeft; ulDom .style.left=curLeft+1+'px'; var curTop=ulDom .offsetTop; ulDom .style.top=curTop+1+'px';
3.3使用absolute或fixed脱离文档流
使用绝对定会使的该元素单独成为渲染树中的body的一个子元素,重排开销比较小,不会对其它节点造成太多的影响,当你在这些节点上放置这个元素时,,一些其它在这个区域内的节点可能需要重绘,但是不需要重排。
或者:先将元素的 display 设置为 none,进行所有的样式和内容的修改。完成修改后,再将其 display 恢复为 block 或其他合适的值,使元素重新显示。