页面的重排和回流(提升移动端网页性能)

一、重绘重排的概念:

  1. 重绘的意思是:重新绘制,如:颜色发生变化,
  2. 重排(回流)的意思是:重新排列,即布局会受影响,如:用js动态改变了元素的宽或高,就会影响其它元素的位置,这叫重新排列。

 

二、什么时候引起重绘,什么时候引起重排:

1、重排(回流):回流这一阶段主要是计算节点的位置和几何信息,那么当页面布局和几何信息发生变化的时候,就需要回流。比如以下情况:

  • 页面一开始渲染的时候(这肯定避免不了)
  • DOM树的结构变化:添加或删除可见的DOM元素
  • DOM元素的几何属性变化:如外边距、内边距、边框厚度、宽高、等几何属性)
  • 内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代。
  • 浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)
  • 窗口属性的获取和尺寸改变:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、 clientTop、clientLeft、clientWidth、clientHeight、getComputedStyle() (currentStyle in IE)
  • Display:的变化。

2、重绘

·DOM元素的字体颜色、改变visibility、outline、背景色。重绘不会带来DOM元素的重新计算,所以重绘并不一定伴随重排(回流),但是重排一定会引起浏览器的重绘

 

三、问题:

重绘,重排太过频繁,就会影响网页的执行性能。亲,你想想:你的页面本来一次可以重排好,你得多重排一次,那肯定是影响性能的。重绘一次就可以,你非得多重绘继承,那肯定也是影响性能的。

跟生活中一样。

重绘:你不停地擦掉重画,擦掉重画,肯定不如一次画到位好

重排:你总是重复性的把某个物体不停地挪动。跟家里的家具要换位置的道理一样。你如果想不来,今晚回去思考一下:假定你要把家里的家具重新布局(从A布局变成B布局),你在家具搬动的过程中,可以出几套搬动方案。看看哪一种搬动方案是挪动家具次数最少的,那么这种方案就是重排的最优方案。

 

四、浏览器的性能优化方案

浏览器也是很聪明的,由于每次重排都会造成额外的计算消耗,因此大多数浏览器都会通过队列化修改并批量执行来优化重排过程。浏览器会将修改操作放入到队列里,直到过了一段时间或者操作达到了一个阈值,才清空队列。但是!当你获取布局信息的操作的时候,会强制队列刷新,比如当你访问以下属性或者使用以下方法:

 

offsetTop、offsetLeft、offsetWidth、offsetHeight

scrollTop、scrollLeft、scrollWidth、scrollHeight

clientTop、clientLeft、clientWidth、clientHeight

getComputedStyle()

getBoundingClientRect()

 

以上属性和方法都需要返回最新的布局信息,因此浏览器不得不清空队列,触发回流重绘来返回正确的值。这也是为什么在获取这些值时会引起重排(回流)、重绘的原因,因此,我们在修改样式的时候,最好避免使用上面列出的属性,他们都会刷新渲染队列。如果要使用它们,最好将值先保存起来。

 

五、如何解决:

 

1、分离读和写的操作(避免触发同步布局事件):


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';

 

因为,获取offsetLeft和offsetTop会导致浏览器强制清空队列,进行强制同步布局。

    

2、样式集中改变,而不要一个一个的改变(减少重绘重排)

   如: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;’

    或者使用class名也可以

ulDom.className = “boxcls”;

 

3、批量修改DOM

1)、如果可以的话,在重排时,可以使用absolute脱离文档流,这样,元素的尺寸改变时,就不会影响其它元素了。先让元素absolute。然后给元素中放入若干个dom,再把元素的absolute去掉;

   如果可以的话,使用display:none(脱离文档流),等元素的样式属性改变完毕后,再让元素显示。

 2)、使用createDocumentFragment或拼接html字符串的方式进行DOM的增加。

发布了219 篇原创文章 · 获赞 347 · 访问量 34万+

猜你喜欢

转载自blog.csdn.net/jiang7701037/article/details/98516468