zoukankan      html  css  js  c++  java
  • 重排重绘与合成

    前端有个很经典的问题是说下重排和重绘的区别,一般我们会说重排性能低,而重绘性能高。但其实我们可以深入探究一下其中但原因。

    重排(回流)

    定义

    当通过JS或者 CSS 修改元素的几何属性,例如改变元素的宽度、高度等,那么浏览器会触发重新布局,解析之后的一系列子阶段,这个过程就叫重排。无疑,重排需要更新完整的渲染流水线,所以开销也是最大的。

    图示

    image.png

    触发条件

    • 添加或者删除可见的DOM元素
    • 元素位置改变
    • 元素尺寸改变
    • 元素内容改变(例: 一个文本被另一个不同尺寸的图片替代)
    • 页面渲染初始化(无法避免)
    • 浏览器窗口尺寸改变

    优化方案

    1. 尽量不要在布局信息改变时做查询(会导致渲染队列强制刷新)。
    2. 合并多次DOM操作。比如用class来改变多个样式。
    3. 避免使用table。
    4. 使用fragment元素(createDocumentFragment
    5. 让元素脱离文档流。即让当前元素有自己的图层。
    6. 多次修改时把dom 离线 ,修改完再显示。(display:none)
    7. 使用采用虚拟DOM的库,如Vue,React
    8. will-change: transform 启用硬件加速

     

    重绘

    定义

    当通过JS或者 CSS 修改元素的绘制属性,例如改变元素的背景颜色,那么布局阶段将不会被执行,因为并没有引起几何位置的变换,所以就直接进入了绘制阶段(即生成待绘制列表),然后执行之后的一系列子阶段,这个过程就叫重绘。相较于重排操作,重绘省去了布局和分层阶段,所以执行效率会比重排操作要高一些。

    图示

    image.png

    触发条件

    • background属性(background,background-color,background-image,background-position,background-repeat,background-size)
    • outline属性(outline,outline-color,outline-style)
    • box-shadow属性
    • border属性(border-style,border-radius)
    • visibility

    优化方案

    1. 合并多次操作

     

    合成

    定义

    更改一个既不要布局也不要绘制的属性,渲染引擎将跳过布局和绘制,只执行后续的合成操作,我们把这个过程叫做合成。比如我们使用了 CSS 的 transform 来实现动画效果,这可以避开重排和重绘阶段,直接在非主线程上执行合成动画操作。这样的效率是最高的,因为是在非主线程上合成,并没有占用主线程的资源,另外也避开了布局和绘制两个子阶段,所以相对于重绘和重排,合成能大大提升绘制效率。

    图示

    image.png

    触发条件

    • will-change
    • transform属性改变
    • 整个图层的几何变换,透明度变换,阴影。

    优化方案

    1. 使用will-change提前声明,使得渲染引擎将该元素单独实现一帧。(空间换时间)。

    ⚠️:每当渲染引擎为一个元素准备一个独立层的时候,它占用的内存也会大大增加,因为从层树开始,后续每个阶段都会多一个层结构,这些都需要额外的内存,所以你需要恰当地使用 will-change。

     

    参考:

    极客时间:浏览器工作原理与实践

    https://blog.csdn.net/qq_42269433/article/details/81133772

  • 相关阅读:
    leetcode 2 Add Two Numbers
    leetcode1
    二叉树的最大高度和最大宽度
    插入排序
    eventEmitter学习
    用node.js做一个爬虫
    HTLM5 WebSocket权威指南
    (new Function("return " + json))();
    JS中的this变量的使用介绍
    node.js 模块加载原理
  • 原文地址:https://www.cnblogs.com/suihang/p/13254471.html
Copyright © 2011-2022 走看看