42.浏览器的重绘与回流

在学习JavaScript的一些总结和经验,供大家参考和学习,同时也欢迎大家参与讨论。

回流


概述: 当一个页面中元素节点的样式改变,影响到它在文档流中的位置和布局时,比如尺寸、结构、几何属性等,浏览器需要重新计算元素的几何属性,并将其绘制出来,重新渲染部分或全部文档的这个过程叫回流(重排)

什么操作会导致回流?

  • 浏览器窗口尺寸大小的变化
  • 页面首次渲染
  • 元素尺寸或位置发生改变(包括外边距、内边框、边框大小、高度和宽度等)
  • 字体大小的改变
  • 激活 CSS 伪类,比如 :hover
  • 内容变化,比如用户在 input 框中输入文字, CSS3 动画等
  • 添加或者删除可见的DOM元素;

常见的引起回流的属性和方法:

clientWidthclientHeightclientTopclientLeft
offsetWidthoffsetHeightoffsetTopoffsetLeft
scrollWidthscrollHeightscrollTopscrollLeft
scrollIntoView()scrollIntoViewIfNeeded()
getComputedStyle()
getBoundingClientRect()
scrollTo()

重绘


概述: 当一个页面中元素节点的样式改变,不影响它在文档流中的位置和布局时,浏览器不需要重新计算元素的几何属性(比如:weidth/height/position/display等),只是把新的样式赋予它,这个过程就叫重绘

什么操作会导致重绘?

  • 改变元素的颜色color
  • 背景颜色background-color
  • visibility
  • 盒子阴影box-shadow
  • 文本阴影

等等等等

触发回流必定会发生重绘,重绘不一定会引发回流

如何减少回流和重绘?

  1. 使用 JavaScript 动态插入多个节点时, 可以使用DocumentFragment. 创建后一次插入;

  2. 减少操作DOM和样式的次数;比如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var element = document.getElementById('test');
    element.style.padding = '5px';
    element.style.borderLeft = '1px';
    element.style.borderRight = '2px';
    // 我们可以把上面的三次操作合并成一次
    var element = document.getElementById('test');
    el.style.cssText += 'border-left: 1px; border-right: 2px; padding: 5px;';
    // 或者使用动态加入class
    var element = document.getElementById('test');
    el.className += ' active';
  1. 少使用display,可以使用visibility代替。

  2. 大量操作DOM的时候可以使用下面的方法。

    • 使元素脱离文档流。
    • 对其进行多次修改。
    • 将元素带回到文档中。
  3. 如果要频繁使用上面介绍的引起回流的属性和方法,可以把它缓存下来,在进行操作。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function initP() {
    for (let i = 0; i < paragraphs.length; i++) {
    paragraphs[i].style.width = box.offsetWidth + 'px';
    }
    }
    // 把会导致浏览器强制清空队列的属性和方法缓存下来
    const width = box.offsetWidth;
    function initP() {
    for (let i = 0; i < paragraphs.length; i++) {
    paragraphs[i].style.width = width + 'px';
    }
    }
  1. 复杂动画效果,使用绝对定位让其脱离文档流

  2. 避免使用 table 布局。

chrome开发者工具种的Rendering面板中的功能

突出显示页面上需要重绘的区域(绿色)

突出显示页面上已移动的区域(蓝色)

显示图层边框(橙色/橄榄色)和图块(青色)

绘制每秒帧数,帧速率分布和GPU内存

突出显示可以减慢滚动速度的元素(tesl),包括touch&wheel事件处理程序和其他主线程滚动情况。

高亮显示检测到是广告的框架(红色)。

参考:

https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction?hl=zh-cn

https://juejin.im/post/5a9923e9518825558251c96a

https://juejin.im/post/5c6cb7b4f265da2dae511a3d

https://anran758.github.io/blog/2018/01/15/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96-%E5%9B%9E%E6%B5%81%E4%B8%8E%E9%87%8D%E6%B1%87/

回流与重绘:css性能让javascript变慢?

视频:

https://www.youtube.com/watch?v=lvb06W_VKVE



文章标题: 42.浏览器的重绘与回流
文章作者: 王奕聪,QQ:1301842163
许可协议: 知识共享许可协议
©署名-非商用-相同方式共享 4.0