• 前端面试题:1.回流与重绘



    怎么理解回流跟重绘?什么场景下会触发?

    一、是什么

    在HTML中,每个元素都可以理解成一个盒子,在浏览器解析过程中,会涉及到回流与重绘:
    回流:布局引擎会根据各种样式计算每个盒子在页面上的大小与位置
    重绘:当计算好盒模型的位置、大小及其他属性后,浏览器根据每个盒子特性进行绘制

    具体的浏览器解析渲染机制如下所示:

    在这里插入图片描述

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

    在页面初始渲染阶段,回流不可避免的触发,可以理解成页面一开始是空白的元素,后面添加了新的元素使页面布局发生改变
    当我们对 DOM 的修改引发了 DOM 几何尺寸的变化(比如修改元素的宽、高或隐藏元素等)时,浏览器需要重新计算元素的几何属性,然后再将计算的结果绘制出来
    当我们对 DOM 的修改导致了样式的变化(color或background-color),却并未影响其几何属性时,浏览器不需重新计算元素的几何属性、直接为该元素绘制新的样式,这里就仅仅触发了回流

    二、如何触发

    回流触发时机
    回流这一阶段主要是计算节点的位置和几何信息,那么当页面布局和几何信息发生变化的时候,就需要回流,如下面情况:

    ●添加或删除可见的DOM元素
    ●元素的位置发生变化
    ●元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
    ●内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代
    ●页面一开始渲染的时候(这避免不了)
    ●浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)
    还有一些容易被忽略的操作:获取一些特定属性的值
    offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight
    这些属性有一个共性,就是需要通过即时计算得到。因此浏览器为了获取这些值,也会进行回流
    除此还包括getComputedStyle 方法,原理是一样的

    重绘触发时机
    触发回流一定会触发重绘
    可以把页面理解为一个黑板,黑板上有一朵画好的小花。现在我们要把这朵从左边移到了右边,那我们要先确定好右边的具体位置,画好形状(回流),再画上它原有的颜色(重绘)
    除此之外还有一些其他引起重绘行为:
    颜色的修改
    文本方向的修改
    阴影的修改

    浏览器优化机制

    由于每次重排都会造成额外的计算消耗,因此大多数浏览器都会通过队列化修改并批量执行来优化重排过程。浏览器会将修改操作放入到队列里,直到过了一段时间或者操作达到了一个阈值,才清空队列
    当你获取布局信息的操作的时候,会强制队列刷新,包括前面讲到的offsetTop等方法都会返回最新的数据
    因此浏览器不得不清空队列,触发回流重绘来返回正确的值

    三、如何减少

    我们了解了如何触发回流和重绘的场景,下面给出避免回流的经验:
    ◆如果想设定元素的样式,通过改变元素的 class 类名 (尽可能在 DOM 树的最里层)
    ◆避免设置多项内联样式
    ◇应用元素的动画,使用 position 属性的 fixed 值或 absolute 值(如前文示例所提)
    ◆避免使用 table 布局,table 中每个元素的大小以及内容的改动,都会导致整个 table 的重新计算
    ◆对于那些复杂的动画,对其设置 position: fixed/absolute,尽可能地使元素脱离文档流,从而减少对其他元素的影响
    ◆使用css3硬件加速,可以让transform、opacity、filters这些动画不会引起回流重绘
    ◆避免使用 CSS 的 JavaScript 表达式

    在使用 JavaScript 动态插入多个节点时, 可以使用DocumentFragment. 创建后一次插入. 就能避免多次的渲染性能

  • 相关阅读:
    关于mac下ubuntu安装20.04的无桌面版后开机后总是进入引导界面
    STM32使用PWM+DMA方式驱动WS2812灯珠
    Mac GPU MPS常用方法
    尚硅谷ES6复习总结上(64th)
    Antd Procomponent 之 proForm - 高级表单
    【AOP系列】6.缓存处理
    哪些场景需要额外注意线程安全问题
    Mysql-主从复制与读写分离
    Maven 脚本批量导入本地jar包
    Go语言学习(八)-- Gin入门
  • 原文地址:https://blog.csdn.net/xiaolu567/article/details/126947136