浏览器重绘(repaint)10bet:重排(reflow)与优化

来源:http://www.chinese-glasses.com 作者:Web前端 人气:54 发布时间:2020-04-15
摘要:结语   这段代码会触发4次重排+重绘,因为在console中你请求的这几个样式信息,无论何时浏览器都会立即执行渲染队列的任务,即使该值与你操作中修改的值没关联。 网页生成的时候

结语

 

这段代码会触发4次重排+重绘,因为在console中你请求的这几个样式信息,无论何时浏览器都会立即执行渲染队列的任务,即使该值与你操作中修改的值没关联。

网页生成的时候,至少会渲染一次。用户访问的过程中,还会不断重新渲染。

因为队列中,可能会有影响到这些值的操作,为了给我们最精确的值,浏览器会立即重排+重绘

 

我们在开发中,应该谨慎的使用这些style请求,注意上下文关系,避免一行代码一个重排,这对性能是个巨大的消耗

function doubleHeight(element) {

  var currentHeight = element.clientHeight;

  window.requestAnimationFrame(function () {

    element.style.height = (currentHeight * 2) + 'px';

  });

}

elements.forEach(doubleHeight);

强制刷新队列:

其中最重要的,就是 window.requestAnimationFrame() 方法。它可以将某些代码放到下一次重新渲染时执行。

它们的代价是高昂的,会破坏用户体验,并且让UI展示非常迟缓,我们需要尽可能的减少触发重排的次数。

**本文转摘自:阮一峰http://www.ruanyifeng.com/blog/2015/09/web-page-performance-in-depth.html**

网页生成过程:HTML被HTML解析器解析成DOM 树css则被css解析器解析成CSSOM 树结合DOM树和CSSOM树,生成一棵渲染树(Render Tree)生成布局(flow),即将所有渲染树的所有节点进行平面合成将布局绘制(paint)在屏幕上

它还可以接受第二个参数,表示指定的毫秒数。如果在指定 的这段时间之内,每一帧都没有空闲时间,那么函数fn将会强制执行。

作者:OBKoro1链接:

 

当我们修改了元素的几何属性,导致浏览器触发重排或重绘时。它会把该操作放进渲染队列,等到队列中的操作到了一定的数量或者到了一定的时间间隔时,浏览器就会批量执行这些操作。

这五步里面,第一步到第三步都非常快,耗时的是第四步和第五步。

当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘。

div.style.color = 'blue';

div.style.marginTop = '30px';

常见引起重排属性和方法

 

dom.display = 'none'// 修改dom样式dom.display = 'block'

四、提高性能的九个技巧:有一些技巧,可以降低浏览器重新渲染的频率和成本。

当p节点上发生reflow时,hello和body也会重新渲染,甚至h5和ol都会收到影响。

 

全局范围:从根节点html开始对整个渲染树进行重新布局。局部范围:对渲染树的某部分或某一个渲染对象进行重新布局

三、对于性能的影响

 /* * 根据上面的结论 * 将 2d transform 换成 3d * 就可以强制开启 GPU 加速 * 提高动画性能 */ div { transform: translate3d(10px, 10px, 0); }

 

  1. 缓存布局信息

    // bad 强制刷新 触发两次重排div.style.left = div.offsetLeft + 1 + 'px';div.style.top = div.offsetTop + 1 + 'px';// good 缓存布局信息 相当于读写分离var curLeft = div.offsetLeft;var curTop = div.offsetTop;div.style.left = curLeft + 1 + 'px';div.style.top = curTop + 1 + 'px';

requestIdleCallback(fn);

网页生成的时候,至少会渲染一次在用户访问的过程中,还会不断重新渲染

重新渲染,就需要重新生成布局和重新绘制。前者叫做"重排"(reflow),后者叫做"重绘"(repaint)。

就如上面的概念一样,单单改变元素的外观,肯定不会引起网页重新生成布局,但当浏览器完成重排之后,将会重新绘制受到此次重排影响的部分

// good

var left = div.offsetLeft;

var top = div.offsetTop;

div.style.left = left + 10 + "px";

div.style.top = top + 10 + "px";

大,在这个语境里的意思是:谁能影响谁?

提高网页性能,就是要降低"重排"和"重绘"的频率和成本,尽量少触发重新渲染。

重排(reflow):概念:

 

计算 offsetWidth 和 offsetHeight 属性

前面提到,DOM变动和样式变动,都会触发重新渲染。但是,浏览器已经很智能了,会尽量把所有的变动集中在一起,排成一个队列,然后一次性执行,尽量避免多次重新渲染。

重绘(repaint):

五、刷新率:

// badvar left = 10;var top = 10;el.style.left = left + "px";el.style.top = top + "px";// goodel.className += " theclassname";// goodel.style.cssText += "; left: " + left + "px; top: " + top + "px;";

 

回流就好比向河里(文档流)扔了一块石头(dom变化),激起涟漪,然后引起周边水流受到波及,所以叫做回流常见引起重排属性和方法

如果想达到60帧的刷新率,就意味着JavaScript线程每个任务的耗时,必须少于16毫秒。一个解决办法是使用Web Worker,主线程只用于UI渲染,然后跟UI渲染不相干的任务,都放在Worker线程。

div.style.left = '10px';div.style.top = '10px';div.style.width = '20px';div.style.height = '20px';

var rAF = window.requestAnimationFrame;

var degrees = 0;

function update() {

  div.style.transform = "rotate(" + degrees + "deg)";

  console.log('updated to degrees ' + degrees);

  degrees = degrees + 1;

  rAF(update);

}

rAF(update);

很多人都知道要减少浏览器的重排和重绘,但对其中的具体原理以及如何具体操作并不是很了解,当突然提起这个话题的时候,还是会一脸懵逼。希望大家可以耐着性子阅读本文,仔细琢磨,彻底掌握这个知识点!

 

  1. 样式集中改变

    div.style.left = '10px';div.style.top = '10px';div.style.width = '20px';div.style.height = '20px';

还有一个函数window.requestIdleCallback(),也可以用来调节重新渲染。不过它是一个很新的函数,刚刚引入标准,目前只有Chrome支持

比如改变元素高度,这个元素乃至周边dom都需要重新绘制。

有一些JavaScript方法可以调节重新渲染,大幅提高网页性能。

内容变化,比如用户在input框中输入文字

上面的代码使用循环操作,将每个元素的高度都增加一倍。可是,每次循环都是,读操作后面跟着一个写操作。这会在短时间内触发大量的重新渲染,显然对于网页性能很不利。

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

 

设置 style 属性的值

二、重排和重绘

在第一个console的时候,浏览器把之前上面四个写操作的渲染队列都给清空了。剩下的console,因为渲染队列本来就是空的,所以并没有触发重排,仅仅拿值而已。

修改DOM

修改样式表

style="font-size: 16px;">用户事件(比如鼠标悬停、页面滚动、输入框键入文字、改变窗口大小等等)

重绘:某些元素的外观被改变,例如:元素的填充颜色重排:重新生成布局,重新排列元素。

上面代码中,只有当前帧的运行时间小于16.66ms时,函数fn才会执行。否则,就推迟到下一帧,如果下一帧也没有空闲时间,就推迟到下下一帧,以此类推。

强制刷新队列的style样式请求

div.style.color = 'blue';

var margin = parseInt(div.style.marginTop);

div.style.marginTop = (margin + 10) + 'px';

建议通过改变class或者csstext属性集中改变样式

 

offsetTop, offsetLeft, offsetWidth, offsetHeightscrollTop, scrollLeft, scrollWidth, scrollHeightclientTop, clientLeft, clientWidth, clientHeightgetComputedStyle(), 或者 IE的 currentStyle

 

常见的引起重绘的属性:

页面滚动事件(scroll)的监听函数,就很适合用 window.requestAnimationFrame() ,推迟到下一次重新渲染。

position属性为absolute或fixed的元素,重排开销比较小,不用考虑它对其他元素的影响

上面代码中,div元素有两个样式变动,但是浏览器只会触发一次重排和重绘。

第四步和第五步是最耗时的部分,这两步合起来,就是我们通常所说的渲染

 

  1. 分离读写操作

    div.style.left = '10px';div.style.top = '10px';div.style.width = '20px';div.style.height = '20px';console.log(div.offsetLeft);console.log(div.offsetTop);console.log(div.offsetWidth);console.log(div.offsetHeight);

 

重排的性能花销跟渲染树有多少节点需要重新构建有关系:

 

渲染:

一秒之间能够完成多少次重新渲染,这个指标就被称为"刷新率",英文为FPS(frame per second)。60次重新渲染,就是60FPS。

本文由10bet发布于Web前端,转载请注明出处:浏览器重绘(repaint)10bet:重排(reflow)与优化

关键词:

频道精选

最火资讯