美文网首页
网页性能篇——回流与重绘

网页性能篇——回流与重绘

作者: 方_糖 | 来源:发表于2019-12-05 17:30 被阅读0次

参考:https://muyiy.cn/question/browser/22.html

一、浏览器渲染的过程

  1. 解析HTML,构建DOM树。解析CSS,构建CSSOM树
  2. DOM树和CSSOM树结合,生成渲染树
  3. 回流(Layout):根据生成的渲染树进行回流,得到节点的几何信息(大小和位置)
  4. 重绘(Painting): 根据渲染树以及已经得到的回流信息,得到节点的绝对像素。
  5. 将像素发送给GPU,展现在页面上

二、什么时候会发生回流与重绘

回流这一阶段主要是计算位置与几何信息,所以当页面布局和几何信息发生变化的时候就需要回流 。比如以下情况

  • 页面一开始渲染的时候
  • 浏览器的窗口发生变化(会重新计算位置和大小)
  • 添加或删除可见的DOM元素
  • 元素的大小(width,height,margin,padding,border-width),位置发生变化
  • 内容发生变化(如图片的url改变)
只发生重绘的情况:改变一些只影响元素外观的样式,而不影响布局(如background改变)

三、浏览器触发回流与重绘

当浏览器获取布局信息时,由于要获取最新的布局信息,所以浏览器不得不清空队列,触发回流重绘来返回准确的值。如修改下面的值:

  • offset~ (offsetTop、offsetLeft、offsetWidth、offsetHeight)
  • scroll~ (scrollTop、scrollLeft、scrollWidth、scrollHeight)
  • client~ (clientTop、clientLeft、clientWidth、clientHeight)
  • getComputedStyle()
  • getBoundingClientRect

三、如何减少回流与重绘

1.合并多次对样式的修改

如:

const el = document.getElementById('test');
el.style.padding = '5px';
el.style.borderLeft = '1px';
el.style.borderRight = '2px';

可以使用cssText合并所有的改变,然后一起处理

const el = document.getElementById('test');
el.style.cssText += 'border-left: 1px; border-right: 2px; padding: 5px;';

或者通过改变className改变样式

const el = document.getElementById('test');
el.className += ' active';
2. 批量修改DOM

如:

function appendDataToElement(appendToElement, data) {
    let li;
    for (let i = 0; i < data.length; i++) {
        li = document.createElement('li');
        li.textContent = 'text';
        appendToElement.appendChild(li);
    }
}

上面代码每一次循环都添加了DOM元素,所以导致了很多次的回流与重绘
所以可以先创建完所有的元素后一次性添加

const ul = document.getElementById('list');
const fragment = document.createDocumentFragment();
appendDataToElement(fragment, data);
ul.appendChild(fragment);
3.避免触发同步布局事件

上文我们提到过,访问一些属性时会导致浏览器强制清空队列,如使用offsetWidth:

function initP() {
    for (let i = 0; i < paragraphs.length; i++) {
        paragraphs[i].style.width = box.offsetWidth + 'px';
    }
}

上面代码每一次循环都访问了offsetWidth,所以导致了很多次的回流与重绘
所以我们要尽量减少访问这类属性

function initP() {
    const width = box.offsetWidth;
    for (let i = 0; i < paragraphs.length; i++) {
        paragraphs[i].style.width = width + 'px';
    }
}
4.对于复杂动画效果,使用绝对定位让其脱离文档流
5.css3硬件加速(GPU加速)

比起考虑如何减少回流重绘,我们更期望的是,根本不要回流重绘。

  • 使用css3硬件加速,可以让transform、opacity、filters这些动画不会引起回流重绘 。
  • 对于动画的其它属性,比如background-color这些,还是会引起回流重绘的,不过它还是可以提升这些动画的性能。

相关文章

网友评论

      本文标题:网页性能篇——回流与重绘

      本文链接:https://www.haomeiwen.com/subject/kxedgctx.html