如何处理网页的重绘和重排问题

爱站 2024-11-03 6 0条评论
摘要: 重绘和重排是浏览器渲染页面的过程中发生的两个关键步骤。重绘指元素样式的变化导致它在屏幕上的外观发生改变,而重排指元素的几何信息发生变化引起页面的重新布局。这两个过程都会消耗大量的系...

重绘和重排是浏览器渲染页面的过程中发生的两个关键步骤。重绘指元素样式的变化导致它在屏幕上的外观发生改变,而重排指元素的几何信息发生变化引起页面的重新布局。这两个过程都会消耗大量的系统资源,从而降低网页的性能。

要减少重绘和重排的影响,可以采取以下措施:

脚本的加载和执行也会阻塞浏览器的渲染过程,影响页面性能。为优化脚本加载,可以采取以下方法:

综合运用这些技巧,可以有效地提高网页的性能和用户体验。


重绘和重排

浏览器渲染引擎工作时,会先解析HTML然后生成DOM树,与此同时,渲染引擎也会用CSS解析器解析CSS文档构建CSSOM树。 接下来, DOM树和CSSOM树关联起来构成渲染树(RenderTree) 然后浏览器按照渲染树进行布局(Layout),最后一步通过绘制显示出整个页面。

单单改变元素的外观,肯定不会引起网页重新生成布局, 但当浏览器完成重排之后,将会重新绘制受到此次重排影响的部分 。 比如改变元素高度,这个元素乃至周边dom都需要重新绘制。

当DOM的变化影响了元素的几何信息(元素的的位置和尺寸大小),浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置,这个过程叫做重排

重排(回流)(reflow)和重绘 (repaint)?如何减少重排和重绘?

重排整个页面 innerHTML可以重绘页面的一部分 1、构建DOM树(parse):渲染引擎解析HTML文档,首先将标签转换成DOM树中的DOM node(包括js生成的标签)生成内容树(Content Tree/DOM Tree); 2、构建渲染树(construct):解析对应的CSS样式文件信息(包括js生成的样式和外部css文件),而这些文件信息以及HTML中可见的指令(如<b></b>),构建渲染树(Rendering Tree/Frame Tree); 3、布局渲染树(reflow/layout):从根节点递归调用,计算每一个元素的大小、位置等,给出每个节点所应该在屏幕上出现的精确坐标; 4、绘制渲染树(paint/repaint):遍历渲染树,使用UI后端层来绘制每个节点。 重绘(repaint或redraw):当盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来之后,浏览器便把这些原色都按照各自的特性绘制一遍,将内容呈现在页面上。 重绘是指一个元素外观的改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。 触发重绘的条件:改变元素外观属性。 如:color,background-color等。 重排(重构/回流/reflow):当渲染树中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建, 这就称为回流(reflow)。 每个页面至少需要一次回流,就是在页面第一次加载的时候。 重绘和重排的关系:在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程称为重绘。 重排必定会引发重绘,但重绘不一定会引发重排。 触发重排的条件:任何页面布局和几何属性的改变都会触发重排,比如: 1、页面渲染初始化;(无法避免) 2、添加或删除可见的DOM元素; 3、元素位置的改变,或者使用动画; 4、元素尺寸的改变——大小,外边距,边框; 5、浏览器窗口尺寸的变化(resize事件发生时); 6、填充内容的改变,比如文本的改变或图片大小改变而引起的计算值宽度和高度的改变; 7、读取某些元素属性:(offsetLeft/Top/Height/Width, clientTop/Left/Width/Height, scrollTop/Left/Width/Height, width/height, getComputedStyle(), currentStyle(IE) ) 重绘发生的情况: 重绘发生在元素的可见的外观被改变,但并没有影响到布局的时候。 比如,仅修改DOM元素的字体颜色(只有Repaint,因为不需要调整布局) 重绘重排的代价:耗时,导致浏览器卡慢。 1、浏览器自己的优化:浏览器会维护1个队列,把所有会引起回流、重绘的操作放入这个队列,等队列中的操作到了一定的数量或者到了一定的时间间隔,浏览器就会flush队列,进行一个批处理。 这样就会让多次的回流、重绘变成一次回流重绘。 2、我们要注意的优化:我们要减少重绘和重排就是要减少对渲染树的操作,则我们可以合并多次的DOM和样式的修改。 并减少对style样式的请求。 (1)直接改变元素的className (2)display:none;先设置元素为display:none;然后进行页面布局等操作;设置完成后将元素设置为display:block;这样的话就只引发两次重绘和重排; (3)不要经常访问浏览器的flush队列属性;如果一定要访问,可以利用缓存。 将访问的值存储起来,接下来使用就不会再引发回流; //例如myElement元素沿对角线移动,每次移动一个像素。 到500*500像素的位置结束。 timeout循环体中可以这么做 //显然这种方法低效,每次移动都要查询偏移量,导致浏览器刷新渲染队列而不利于优化。 好的办法是获取一次起始位置的值,然后赋值给一个变量。 如下 (4)使用cloneNode(true or false) 和 replaceChild 技术,引发一次回流和重绘; (5)将需要多次重排的元素,position属性设为absolute或fixed,元素脱离了文档流,它的变化不会影响到其他元素; (6)如果需要创建多个DOM节点,可以使用DocumentFragment创建完后一次性的加入document; (7)尽量不要使用table布局。 不管页面发生了重绘还是重排,它们都会影响性能(最可怕的是重排 ,应尽量避免) DOM:描述该页面的结构 render:描述 DOM 节点 (nodes) 在页面上如何呈现 当 DOM 元素的属性发生变化 (如 color) 时, 浏览器会通知 render 重新描绘相应的元素, 此过程称为 repaint。 如果该次变化涉及元素布局 (如 width), 浏览器则抛弃原有属性, 重新计算并把结果传递给 render 以重新描绘页面元素, 此过程称为 reflow。 这两个过程是很耗费浏览器性能的, 从 IE 系列和 Chrome 渲染页面速度上的差距即可看出渲染引擎计算对应值和呈现并不一定高效, 而每次对元素的操作都会发生 repaints 或 reflow, 因此编写 DOM 交互时如果不注意就会导致页面性能低下. 页面渲染的过程如下: 原文:

回流(重排)和重绘

1.1 重绘 重绘是指页面中某些元素发生了不影响布局的变化时(如颜色改变),浏览器重新绘制的过程。 此时由于只需要UI层面的重新像素绘制,因此损耗较少。 仅仅 引发重绘的操作如下所示(注意:回流必定触发重绘,但是重绘不一定触发回流): 1)改变背景色; 2)改变文字颜色; 3)改变边框颜色; 通过visibility:hidden隐藏元素; …… 1.2 回流 回流是指页面中某些元素发生变化而影响了布局时(如尺寸、位置改变),浏览器需要重新布局并绘制的过程。 引发回流的操作如下所示: 1)页面初次渲染; 2)浏览器窗口大小改变; 3)元素尺寸、位置、内容发生改变; 4)元素字体大小变化; 5)添加或者删除可见的 dom 元素; 5)激活 CSS 伪类(例如::hover); 6)查询某些属性或调用某些方法: clientWidth、clientHeight、clientTop、clientLeft offsetWidth、offsetHeight、offsetTop、offsetLeft scrollWidth、scrollHeight、scrollTop、scrollLeft getComputedStyle() ()方法返回一个对象,该对象在应用活动样式表并解析这些值可能包含的任何基本计算后报告元素的所有CSS属性的值。 getBoundingClientRect() scrollTo():scrollTo() 方法可把内容滚动到指定的坐标。 1.3 减少回流和重绘 1.3.1 浏览器自身优化策略 由于每次重排都会造成额外的计算消耗,因此大多数浏览器都会通过队列化修改并批量执行来优化重排过程。 浏览器会将修改操作放入队列里,直到过了一段时间或者操作达到了一个阈值,才清空队列。 当你获取布局信息的操作的时候,会强制队列刷新,比如访问以下属性或者使用以下方法: offsetTop、offsetLeft、offsetWidth、offsetHeight scrollTop、scrollLeft、scrollWidth、scrollHeight clientTop、clientLeft、clientWidth、clientHeight getComputedStyle() getBoundingClientRect 以上属性和方法都需要返回最新的布局信息,因此浏览器不得不清空队列,触发回流重绘来返回正确的值。 因此,在修改样式的时候,最好避免使用上面列出的属性,它们都会刷新渲染队列。 如果要使用它们,最好将值缓存起来。 另一优化就是浏览器认为position为absolute或fixed的元素更改只会影响其本身和子元素,而static的元素变化则会影响之后的所有元素。 原因在于absolute和fixed认为元素从文档流中清除了,怎么操作是内部的事。 例如:对于复杂动画效果,使用绝对定位让其脱离文档流 1.3.2 多次操作变为一次操作 不要一条一条的修改DOM的样式,尽量使用class进行样式修改。 把DOM离线修改(批量修改DOM) 1)使用documentFragment对象在内存里操作DOM 2)先把DOM给display:none,修改完毕再显示出来 3)clone一个DOM节点到内存里,然后想怎么改就怎么改,改完后,和在线的那个的交换一下。 1.3.3 其它 使用css3硬件加速,可以让transform、opacity、filters(滤镜)这些动画不会引起回流重绘(注意:对于动画的其它属性,比如background-color这些,还是会引起回流重绘的,不过它还是可以提升这些动画的性能) 不要把DOM结点的属性值放在一个循环里当成循环里的变量。 不然这会导致大量地读写这个结点的属性。 千万不要使用table布局。 因为可能很小的一个小改动会造成整个table的重新布局。

文章版权及转载声明:

作者:爱站本文地址:https://www.awz.cc/post/4458.html发布于 2024-11-03
文章转载或复制请以超链接形式并注明出处爱网站

赞(0