浏览器 - 是谁触发了浏览器的重绘和回流

重绘和回流是在页面渲染过程中的非常重要的两个概念。页面生成后,页面操作、样式表变更以及用户操作都可能出发重绘和回流。

回流

回流reflow,有时候也叫重排relayout

回流是指窗口尺寸被修改,发生滚动操作,或者是元素的尺寸或位置相关属性被更新时会出发布局过程,在布局过程中需要重新计算所有元素的位置信息。由于HTML元素使用的流式布局,如果页面中一个元素位置或尺寸发生了变化,则后面的元素的位置都要跟着发生变化,也就是重新进行流式布局的过程,所以被称为回流。

回流发生在页面的渲染过程中。一般如下操作会触发回流:

  1. DOM元素的几何属性发生变化,如尺寸(width),位置(psoition)等
  2. DOM树结构发生变化
  3. 调整浏览器窗口大小
  4. 改变元素的一些样式,如display,float等等
  5. 获取下列属性时:
offsetTop/offsetLeft/offsetWidth/offsetHeight/scrollTop/scrollLeft/scrollWidth/scrollHeight/clientTop/clientLeft/clientHeight/getComputedStyle()/currentStyle()

重绘

重绘是指当与视觉相关的样式属性值发生变化时会触发绘制的过程,在绘制过程中要重新计算元素的视觉信息,使元素呈现新的外观。由于元素重绘只发生在渲染层上,所以如果要改变元素的视觉属性,最好让该元素成为一个独立的渲染层。比如,当元素的背景

下面以一个元素的显示和隐藏来说明回流和重绘:

display:none/block,会引起回流,从而引起重绘,性能较差

visibility:visible/hidden,只会引起重绘,但由于没有成为一个独立的渲染出,会引起整个页面的重绘。性能相对较好

opacity:opacity在0和1的变化中会引起render层的生成和销毁,因此会引发一次回流,从而引发重绘。如果opacity在0-0.9间变化则只会引发重绘。

tips

触发回流一定会引起重绘,而且对一个元素的回流,可能会影响到父级元素。比如子元素浮动后,父元素会出现高度塌陷的情况。所以性能优化的重点在于尽量只触发小规模的重绘,尽量不触发回流。

性能优化

  1. 不要一条一条的修改DOM样式,而是修改className或者修改style.cssText
  2. 在内存中多次操作节点,完成后在添加到文档中,比如要创建5个div元素,不要创建一个append一个,这样会引发5次回流,而是先创建一个documentFrament,然后将5个div append到frament中然后再将frament append到文档中,这样就只会引发一次回流。
  3. 对一个元素进行复杂操作时,可以先隐藏它,操作完成后在显示。
  4. 在需要经常获取那些容易引起浏览器回流的属性时,要缓存到变量中
  5. 不要使用table布局,因为一个小小的改动可能会造成整个table的重新布局。而且table渲染通常要3倍于同等元素时间。
  6. 在对DOM的样式属性操作时要进行读写分离。例如:
//引发两次回流
var div = document.querySelector('myDiv');
div.style.width = '300px';
var w = document.style.width;
div.style.height = '300px';
var h = document.style.height;

//只引发一次回流
var div = document.querySelector('myDiv');
div.style.width = '300px';
div.style.height = '300px';

var w = document.style.width;
var h = document.style.height;

上面的代码中,同样是读取和设置div的高度和宽度操作。第一段代码就会引发两次回流,这是因为浏览器在进行解析时,当遇到会引发回流的代码时,它不是直接改变dom属性,而是等待看下一行代码是否也会引发回流,如果是则两句代码一起执行,如果没有则将上一句代码执行。所以要进行读写分离。

猜你喜欢

转载自blog.csdn.net/lixiaosenlin/article/details/108262343