页面回流与重绘的那点事儿

页面渲染过程

在这里插入图片描述

  1. 浏览器把HTML代码解析成一颗DOM Tree,每个元素标签都是DOM Tree中的一个节点,根节点是Document
  2. 在形成DOM Tree后,从DOM Tree根节点开始,遍历每一个可见的节点,并找到合适的、匹配的CSSOM规则,应用在节点上;
  3. DOM TreeCSSOM Tree连接在一起形成Render Tree
  4. 最终绘制出页面,显示在屏幕上

什么叫回流与重绘?

  • 页面回流:当render tree中的一部分(或全部)因为元素的规模尺寸、布局、隐藏等改变而引起的页面重新渲染(或者叫作重新构建绘制);
  • 页面重绘:当render tree中的一些元素需要更新属性,但这些属性只会影响元素的外观、风格,而不会影响元素的布局,此类的页面渲染叫作页面重绘。

在网页生成的时候,至少会渲染一次。用户访问的过程中,任何对Render Tree节点的操作都会引起重新渲染。
需要注意的是页面重绘不一定会引起回流,但回流一定会引起页面重绘。

常见的回流与重绘操作

  1. DOM节点的添加、删除;
  2. 调整窗口大小(resize事件);
  3. 元素位置改变、元素尺寸改变(width/height/padding/border/margin);
  4. CSS伪类的激活(如hover);
  5. 对样式的操作(不同属性有不同的影响)
  6. 元素样式属性的读取操作

不同样式的操作造成回流、重绘影响

开发过程中,提高性能的技巧

页面的回流、重绘在项目中是不可避免的,但过高、频繁的回流、重绘必定导致网页性能低下,影响客户体验感。所以,在开发过程中,我们应尽可能的避免回流、重绘,尽量少触发页面的重新渲染。

1. 尽量不要把读操作和写操作,放在一个语句里面。
// 下列操作只会造成一次回流、重绘
div.style.color = 'blue';
div.style.marginTop = '30px';

// 下列操作造成两次的回流、重绘
div.style.color = 'blue';
var margin = parseInt(div.style.marginTop);
div.style.marginTop = (margin + 10) + 'px';

在样式的写操作之后,有对元素进行offsetscrollclientgetComputedStyle()属性读取操作,都会触发浏览器立即重新渲染。

// 坏的写法 --> 读写操作放同一个语句
div.style.left = div.offsetLeft + 10 + "px";

// 好的写法
var left = div.offsetLeft;
div.style.left = left + 10 + 'px';
2. 不要一条条地修改样式,而是通过改变classcssText属性,一次性修改样式。
// 坏的写法
div.style.left = '10px';
div.style.top  = '10px';

// 好的写法
div.className += 'newClassName';

div.style.cssText += 'background-color:red;font-size:20px;';
3. 尽可能使用Document Fragment对象或者cloneNode(),在克隆的节点上进行操作,然后再用克隆的节点替换原始节点。
// 坏的写法
for( var i = 0; i<2; i++ ){
    var li = document.createElement('li');
    li.textContent = i;
    ul.appendChild(li);
}

// 好的写法
var fragment = document.createDocumentFragment();
for( var i = 0; i<2; i++ ){
    var li = document.createElement('li');
    li.textContent = i;
    fragment.appendChild(li);
}
ul.appendChild(fragment);
4. 先将元素设置为display:none,再对元素进行操作,最后恢复显示,这样只需要两次的重新渲染。
5. 尽可能地使用position;,而不是float来进行元素浮动。因为使用position属性不用考虑它对其他元素的影响,回流的开销会比较小。
6. 尽可能地将display属性设为可见,不可见属性的元素不会影响回流和重绘 (visibility的元素只对重绘有影响,不影响回流)。
7. 使用虚拟DOM的脚本库,比如ReactVue等。
8. 使用window.requestAnimationFrame()window.requestIdleCallback()这两个方法调节重新渲染。

注意:window.requestAnimationFrame()只能在IE10及以上使用,而window.requestIdleCallback()在IE上是不支持的。这两个方法在阮一峰阮一峰的博客上有详细的介绍。

参考链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值