在HTML
中,每个元素都可以理解成一个盒子,在浏览器解析过程中,会涉及到重排与重绘。
一、什么是重绘(repaint)和重排(reflow)
重绘:当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘。
重排:当DOM的变化影响了元素的几何信息(元素的的位置和尺寸大小),浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置,这个过程叫做重排。
局部范围重排:把dom的宽高之类的几何信息定死,然后在dom内部触发重排,就只会重新渲染该dom内部的元素,而不会影响到外界。
浏览器解析渲染机制如下:
①.解析HTML,生成DOM树,解析CSS,生成CSSOM树
②.将DOM树和CSSOM树结合,生成渲染树(Render Tree)
③.Layout(回流):根据生成的渲染树,进行回流(Layout),得到节点的几何信息(位置,大小)
④.Painting(重绘):根据渲染树以及回流得到的几何信息,得到节点的绝对像素
⑤.Display:将像素发送给GPU,展示在页面上
在页面初始渲染阶段,回流不可避免的触发,可以理解成页面一开始是空白的元素,后面添加了新的元素使页面布局发生改变。
当我们对 DOM 的修改引发了 DOM几何尺寸的变化(比如修改元素的宽、高或隐藏元素等)时,浏览器需要重新计算元素的几何属性,然后再将计算的结果绘制出来。
二、常见的引起重绘的属性
color | border-style | visibility | background | text-decoration |
background-image | background-position | background-repeat | outline-color | outline |
outline-style | border-radius | box-shadow | background-size | outline-width |
三、常见引起重排属性和方法
width | height | margin | padding | display |
border-width | border | position | overflow | font-size |
vertical-align | min-height | clientWidth | clientHeight | clientTop |
clientLeft | scrollWidth | scrollHeight | scrollTop | scrollLeft |
getComputedStyle() | getBoundingClientRect() | scrollIntoViewIfNeeded() | 伪类:如:hover |
四、什么情况下会触发重绘
触发回流时一定会触发重绘,除此之外,例如颜色修改,设置圆角、文本方向修改,阴影修改等。
五、什么情况下会触发回流
回流这一阶段主要是计算节点的位置和几何信息,那么当页面布局和几何信息发生变化的时候,就需要回流,如下面情况:
①.添加或删除可见的DOM元素
②.元素的位置发生变化
③.元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
④.内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代
⑤.页面一开始渲染的时候(这避免不了)
⑥.浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)
提示:重绘不一定导致重排,但重排一定会导致重绘。
六、浏览器优化机制
由于每次重排都会造成额外的计算消耗,因此大多数浏览器都会通过队列化修改并批量执行来优化重排过程。浏览器会将修改操作放入到队列里,直到过了一段时间或者操作达到了一个阈值,才清空队列。
当你获取布局信息的操作的时候,会强制队列刷新,包括前面讲到的offsetTop等方法都会返回最新的数据。因此浏览器不得不清空队列,触发回流重绘来返回正确的值。
七、重排优化方案有哪些?
一、减少重排的范围
①.尽可能的在DOM树的最末端改变class,重排是不可避免的,但是可以减少其影响,尽可能的在DOM树的最末端改变class,可以限制重排的范围,尽可能少的影响其他节点。
②.不要使用table布局,可能很小的一个小改动会造成整个table的重新布局,在不得已使用table的场合,可以设置table-layout:auto,或者table-layout:fixed,这样可以让table一行一行的渲染,这种做法是为了限制reflow的影响范围。
二、减少重排的次数
①.样式集中改变
不要频繁的操作样式,对于一个静态页面来说,明智且可维护的做法是更改类名,而不是修改样式。对于动态改变的样式来说,相较每次微小修改都直接触及元素,更好的办法是统一在cssText变量中编辑。虽然现在大部分现代浏览器会有flush队列进行渲染队列优化,但是有些老版本的浏览器效率依然低下。
②.分离读写操作
DOM的多个读操作或者写操作,应该放在一起,不要两个读操作之间加入一个写操作
当我们修改了元素的集合属性,导致浏览器触发重排或重绘时,它会把该操作放进渲染队列,等到队列中操作到了一定的数量或者到了一定的时间间隔时,浏览器就会批量执行这些操作。
③.将DOM离线
使用display:none; 一旦我们给元素设置display:none时(只有一次重排重绘),元素便不会再存在在渲染树种,相当于将其从页面上“拿调”,我们之后的操作将不会触发重绘和重排,添加足够多的变更后,通过display属性显示(另一次重排重绘)。通过这种方式即时大量变更也只是触发两次重排,visibility:hidden的元素只对重绘有影响,不影响重排
通过documentFragment创建一个dom碎片,在它上面批量操作dom,操作完成之后,再添加到文档中,这样只会触发一次重排。
复制节点,在副本上工作,然后替换他。
④.使用absolute或fixed脱离文档流
使用绝对定会使的该元素单独成为渲染树中的body的一个子元素,重排开销比较小,不会对其它节点造成太多的影响,当你在这些节点上放置这个元素时,,一些其它在这个区域内的节点可能需要重绘,但是不需要重排。文章来源:https://www.toymoban.com/news/detail-440461.html
⑤.优化动画
可以把动画效果应用到position属性为absolute或fixed的元素上,这样对其他元素影响较小。
启用GPU加速GPU硬件加速是指应用GPU的图形性能对浏览器中的一些图形操作交给GPU来完成,GPU专门是为处理图形而设计的,在速度和能耗上更有效率。文章来源地址https://www.toymoban.com/news/detail-440461.html
到了这里,关于什么是重绘和重排的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!