浏览器渲染机制:重排(Reflow)与重绘(Repaint)以及Vue优化策略

在这里插入图片描述

浏览器渲染机制是一个复杂但有序的过程,其目的是将HTML、CSS和JavaScript代码转化为用户可以看到和交互的视觉界面。重排(Reflow)与重绘(Repaint)是浏览器渲染过程中对页面元素进行更新的两个重要步骤,理解它们的工作机制有助于我们进行性能优化。本文介绍了浏览器渲染机制,重排、重绘概念,以及何时会发生重排、重绘以及如何避免不必要的重排、重绘,提升性能。另外,介绍了Vue优化重排和重绘机制以及开发者在实际项目中可以采取的优化重排和重绘策略。

一、浏览器渲染机制:

1. 解析HTML并构建DOM树 (Document Object Model)

  • 当浏览器接收到HTML文档时,会通过HTML解析器逐行读取和解析文档内容,将标签、属性和文本内容转换为DOM节点,构建一棵表示文档结构的树状模型。

示例:

<html><head><title>页面标题</title></head><body><div id="content"><h1>Hello, World!</h1><p>这是一个简单的示例。</p></div></body>
</html>

对应的DOM树将有一个html根节点,下面依次挂载headbody节点,body内包含一个div节点和它的子节点h1p节点。

2. 解析CSS并构建CSSOM树 (CSS Object Model)

  • 浏览器同时解析CSS样式表,无论是外链样式表还是内嵌样式,都将CSS规则转换成CSSOM树。CSSOM树记录了所有的样式规则和它们应用到哪些DOM元素上。

3. 生成渲染树 (Render Tree)

  • 渲染树是由DOM树和CSSOM树合并而成的,它仅包含可见内容(即没有display: none等隐藏属性的节点),且每个节点都包含了自身及其计算后的样式信息。
  • 示例中,渲染树将包括body内的divh1p节点,以及应用于它们的所有样式。

4. 布局 (Layout / Reflow)

  • 在生成渲染树之后,浏览器会进行布局(也称回流,Reflow)。此阶段,浏览器会计算每个渲染对象在视口(viewport)中的具体几何位置和尺寸,包括宽度、高度以及相对于父元素或视口的位置。
  • 假设CSS中设置了div#content { width: 80%; margin: auto },那么在布局阶段,浏览器会计算div#content占据视口宽度的80%,并居中显示。

5. 绘制 (Paint / Repaint / Composite)

  • 完成了布局阶段后,浏览器按照渲染树顺序进行绘制,将各个节点的内容、背景、边框、阴影等视觉信息通过图形处理器(GPU)绘制到屏幕上。
  • 如果元素需要重叠,浏览器还会对部分或全部内容进行分层处理(compositing),例如使用transformopacity属性的元素会被提升到单独的图层进行合成。

6. 增量渲染与优化

  • 当DOM变化时,浏览器尽可能地只重新计算受影响部分的布局和绘制,而不是全局重新渲染。例如,改变某个元素的颜色通常只会触发重绘(Repaint),而不改变布局的话,则不需要回流(Reflow)。

总之,浏览器通过以上步骤确保页面内容快速、准确地呈现在用户面前。在实际开发中,了解这一机制有助于优化页面性能,减少不必要的重排和重绘操作。

二、重排(Reflow)

重排(Reflow)是指在Web前端开发中,当浏览器渲染树中DOM元素的几何属性发生变化,或者由于某种原因需要重新计算布局时,浏览器重新计算元素的几何尺寸、相对位置以及其他相关的CSS属性,并更新渲染树的过程。这个过程可能会影响渲染树中其他元素的位置和尺寸,因此常常伴随着一系列连锁反应,对于复杂的页面结构和大量DOM元素而言,重排可能会消耗较大的计算资源,影响页面性能。

1.何时会发生重排:

重排通常发生在以下几种情况下:

1.1. DOM 结构变化

  • 添加或删除可见DOM元素。
  • 元素的内容发生变化导致尺寸变化,比如文字数量改变使得容器高度增加。

1.2. 样式属性变更

  • 影响元素几何属性的CSS属性发生变化,例如:
    • 宽度(width)、高度(height)、外边距(margin)、内边距(padding)、边框(border)等。
    • 顶部、底部、左边、右边定位(top, bottom, left, right)。
    • 浮动(float)状态改变。
    • display属性更改(例如从none变为block)。
    • flexgrid布局中的相关属性更改。

1.3. 获取某些布局信息

  • 当JavaScript请求读取依赖于布局信息的样式属性,如offsetTop, offsetLeft, scrollTop, scrollWidth等时,浏览器可能会触发重排以便给出精确值。

1.4. 窗口或设备视口尺寸变化

  • 用户调整浏览器窗口大小时,特别是响应式设计场景。

2.如何避免不必要的重排

2.1. 合并DOM操作

  • 如果需要对多个元素进行改动,尽量一次性完成,而不是分散在多处代码中分别操作。
// 避免的做法
for (var i = 0; i < elements.length; i++) {elements[i].style.width = '100px';
}// 优化做法
var style = 'width: 100px;';
for (var i = 0; i < elements.length; i++) {elements[i].style.cssText += style; // 一次性设置所有元素样式
}

2.2. 离屏DOM操作

  • 使用DocumentFragment创建子节点,完成后一次性插入DOM树中。
// 创建一个文档片段
var fragment = document.createDocumentFragment();// 在文档片段中构建DOM结构
for (var i = 0; i < 100; i++) {var el = document.createElement('div');el.textContent = 'Item ' + i;fragment.appendChild(el);
}// 一次性将文档片段加入DOM
document.getElementById('container').appendChild(fragment);

2.3. 使用CSS动画替代JavaScript动画

  • 使用CSS3的transitionanimation来改变元素的位置或尺寸,而非直接修改样式,因为CSS动画通常仅引发重绘而非重排。
.box {transition: all 0.5s ease-in-out;
}// JavaScript 中只需切换类名即可
element.classList.add('move');

2.4. 预读取布局信息

  • 如果需要连续读取布局信息,先读取后操作,避免在操作过程中反复查询。
// 获取原始位置,同时触发一次重排
var originalTop = element.offsetTop;// 后续操作不再触发重排
element.style.top = originalTop + 'px';

2.5. 使用绝对定位

  • 对于需要频繁改变位置或尺寸的元素,使用position: absolutefixed可以使其脱离文档流,独立于常规布局系统,从而限制重排的影响范围。

2.6. 优化CSS选择器

  • 避免过于复杂的选择器,以免每次样式更改时导致大量元素的重排。

2.7. 使用硬件加速

  • 使用transform: translateZ(0)will-change属性提示浏览器针对特定属性进行硬件加速,有助于减少重排。

通过以上措施,可以有效减少不必要的重排,从而提高页面渲染性能。注意,虽然这里提供了部分示例,但实际优化还需要结合具体应用场景进行分析。随着浏览器引擎的进步,一些低级别的优化细节可能有所变化,最新的最佳实践建议参考官方文档和最新的性能测试结果。

三、重排(Reflow)

重绘(Repaint)在Web前端开发领域特指浏览器的一种渲染操作。当网页中元素的样式(style)发生改变,但这种改变不影响元素在文档布局(layout)中的位置和尺寸时,浏览器仅需要重新绘制(即重绘)受影响部分的像素,以反映元素新的视觉表现。重排可能会消耗较大的计算资源,影响页面性能。

1.何时会发生重绘(Repaint):

重绘通常发生在以下几种情况:

1.1. 视觉表现相关的样式属性改变

  • 改变元素的颜色(color)、背景色(background-color)、边框颜色(border-color)、阴影(box-shadow)、不透明度(opacity)等不影响布局的视觉属性。
  • 图像资源(如src属性)加载完成或变化。
  • 文本内容变化,但并未引起元素尺寸变化。

1.2. 伪类或伪元素激活

  • 当:hover、:focus等伪类被触发,或者:before、:after等伪元素样式发生变化时。

1.3. 元素透明度变化

  • 当元素的opacity属性改变时,不仅当前元素会重绘,其下面的所有内容也可能受到影响,因为它们都需要重新混合。

2.如何避免不必要的重绘:

以下是减少重绘的策略及其示例:

2.1. 批量修改样式

  • 避免逐个更改元素样式,可以先将新的样式保存在一个变量中,然后一次性赋值给元素。
// 避免的做法
element.style.color = 'red';
element.style.backgroundColor = 'blue';// 优化做法
element.style.cssText = 'color: red; background-color: blue;';
// 或
var newStyle = element.className;
newStyle += ' my-red-background-class';
element.className = newStyle;

2.2. 使用CSS类代替直接样式修改

  • 修改元素的class属性来应用预先定义好的样式,而不是直接修改单个样式属性。
/* CSS */
.red-background { background-color: red; }// JavaScript
element.classList.add('red-background');

2.3. 避免不必要的视觉属性变化

  • 如果只是简单地改变颜色或背景色,而这些改变并不影响用户体验,可以在用户交互的关键时刻(例如鼠标悬停或焦点事件)才触发重绘。

2.4. 利用CSS3动画与过渡

  • 使用CSS transitionanimation 规则来处理动画效果,相比JavaScript定时器不断修改样式属性,CSS动画能够更高效地处理重绘。
.box {transition: background-color 0.5s ease;
}// JavaScript 中只需切换类名
element.classList.add('change-color');

2.5. 利用合成层(Compositing Layers)

  • 当元素启用3D变换或使用will-change属性时,浏览器可能将元素放入独立的图层进行渲染,这可以将重绘限制在单个图层内部,而不影响其他元素。
.element-to-animate {will-change: transform;/* 或 */transform: translateZ(0); /* 触发硬件加速 */
}

2.6. GPU加速

  • 使用硬件加速特性(如transformopacity)来进行动画处理,因为GPU能高效处理这类属性的变化,且通常不会触发其他元素的重绘。

通过上述方法,可以减少不必要的重绘次数,进而提升页面渲染效率。同样地,请关注浏览器性能优化的最佳实践和最新进展,以适应不断发展的技术和标准。

四、Vue 重排、重绘

在Vue.js中,由于其响应式设计和虚拟DOM(Virtual DOM)机制,Vue自动在很大程度上进行了重排(Reflow)和重绘(Repaint)相关的性能优化。Vue通过追踪数据变化并在必要时更新视图,而不是每次数据变动就立即操作实际DOM,有效地减少了无谓的重排和重绘。

1、Vue优化重排与重绘优化

1.1. 虚拟DOM

  • 当数据发生变化时,Vue会基于新的数据生成一个新的虚拟DOM树。
  • Vue通过算法比较新旧虚拟DOM树的差异(diff算法),找出最小化的变更集。
  • 只将真正变化的部分反映到实际DOM中,这样极大地减少了触发浏览器重排和重绘的DOM操作。

1.2. 异步更新队列

  • Vue并不会立即执行所有的数据更改,而是将它们收集在一个队列中。
  • 在下一个事件循环tick中,Vue会把队列中的变化批量更新到真实DOM,这有助于合并多个更新操作,避免连续的重排和重绘。

1.3. 组件级更新

  • Vue组件有自己的局部作用域,因此组件内部的更新只会影响该组件及其子组件,不会引发全局的重排和重绘。

1.4. 事件委托与防抖节流

  • Vue鼓励开发者采用事件委托,减少直接在DOM节点上的事件绑定,从而降低DOM操作带来的重排重绘风险。
  • 对于可能频繁触发更新的方法,可以通过防抖(debounce)或节流(throttle)函数进行优化,避免过度频繁的UI更新。

2、开发者优化重排和重绘

Vue.js 开发者在优化重排(reflow)和重绘(repaint)方面可以采取以下策略:

  • 利用Vue的响应式原理

    • Vue.js通过虚拟DOM和高效的Diff算法自动优化了大部分DOM操作。当状态变化时,Vue只会更新受影响的DOM部分,而不是整个页面,以此减少不必要的重排和重绘。
  • 减少不必要的数据观察

    • 尽量避免不必要的深度监听或大量对象属性的观察。对于大型对象,可以考虑浅层监听或使用Object.freeze()等方法防止意外修改。
  • 组件级别的优化

    • 组件拆分和复用有助于限制DOM更新范围。在独立组件内做状态变更,能够使重排重绘的影响局限在组件内部。
  • CSS样式优化

    • 使用CSS类名代替直接修改样式属性,因为修改类名通常只会触发重绘而不会触发重排。
    • 将不会改变布局的样式(如颜色、透明度等)单独更改,减少强制重排的情况。
  • 异步更新队列

    • Vue会把同一事件循环 tick 中的数据变化集中起来,一次性更新DOM,利用 this.$nextTick() 确保在DOM更新后执行依赖于DOM状态的操作。
  • 列表渲染优化

    • 对于大型列表,使用v-for时,给每一项加上唯一的key,Vue会更加高效地跟踪和更新项目。
    • 针对长列表滚动场景,可以结合Intersection Observer API或者Vue自己的<infinite-scroll>组件实现懒加载和虚拟滚动,仅渲染视口内的元素。
  • 避免频繁的DOM查询

    • 减少在组件生命周期钩子或计算属性中使用document.querySelector()this.$refs频繁查找DOM元素的操作,这类操作可能会触发重排。
  • 事件委托和节流防抖

    • 将事件处理器委托到父元素上,减少直接绑定到大量子元素上的事件监听器。
    • 对于高频触发的事件,例如窗口大小变化或滚动事件,使用节流(throttle)或防抖(debounce)函数来限制更新频率。
  • 批处理DOM更新

    • 如果需要执行一系列可能导致DOM更新的操作,尝试将其合并到一个Vue实例的生命周期钩子(如updated)中一次性完成。
  • 使用Portals或者Render Functions

    • 在特定情况下,可以通过Vue的render函数或者Portal技术将组件渲染到非当前组件树层级的位置,这样可以避免深层嵌套组件导致的过度重排。

综上所述,Vue开发人员在实践中应当充分理解Vue的工作原理,并结合上述建议来编写高性能、低重排重绘开销的代码。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/4602.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu22.04安装TensorRT(过程记录)

重要说明&#xff1a;此贴经过多次修改。第一次安装的的为trt8.6.1版本。第二次安装的10.0.0.6版本。有些地方可能没改过来&#xff0c;比如链接向导&#xff0c;我懒得改了&#xff0c;但是流程是对的。 cuda和cudnn版本对应关系 tensorRT历史发行版本 CUDA历史发行版本 cudn…

ENVI不同版本个人使用对比

ENVI不同版本个人使用对比 文章目录 ENVI不同版本个人使用对比前言对比5.3学习版5.6学习版6.0试用版 总结 前言 目前来看&#xff0c;流传较广的可供大家免费获取的ENVI版本主要是5.3学习版 5.6学习版 6.0学习版这三个版本&#xff0c;不同的版本有不同特色&#xff0c;在此做…

C#基础|StringBuilder字符串如何高效处理。

哈喽&#xff0c;你好&#xff0c;我是雷工。 字符串处理在C#程序开发中是使用频率比较高的&#xff0c;但常规的字符串处理方式对内存占用比较多&#xff0c;为了优化内存&#xff0c;减少不必要的内存浪费&#xff0c;引入了StringBuilder类。 下面学习下StringBuilder类的使…

PC-3000 Flash:NAND 闪存设备(包括一体式U盘)数据恢复的重量级工具(一)

天津鸿萌科贸发展有限公司从事数据安全业务20余年&#xff0c;在数据恢复、数据取证、数据备份等领域有丰富的案例经验、前沿专业技术及良好的行业口碑。同时&#xff0c;公司面向取证机构及数据恢复公司&#xff0c;提供数据恢复实验室建设方案&#xff0c;包含 PC-3000 系列数…

LeetCode 热题 100 Day05

矩阵相关题型 Leetcode 73. 矩阵置零【中等】 题意理解&#xff1a; 将矩阵中0所在位置&#xff0c;行|列置换为全0 其中可以通过记录0元素所在的行、列号&#xff0c;来标记要置换的行|列 将对应位置置换为0 解题思路&#xff1a; 第一个思路&#xff1a; 可以…

React | classnames

classnames 这个库在我们的项目中有大量的使用到&#xff0c;它不仅很实用&#xff0c;还非常好用&#xff0c;但还有人不知道这个库&#xff0c;我真的是十分心痛。 通过 classnames&#xff0c;我们可以给组件设置多个 className&#xff0c;还可以根据需要动态设置 classNa…

模块四:前缀和——DP35 【模板】二维前缀和

文章目录 题目描述算法原理解法一&#xff1a;暴力模拟&#xff08;时间复杂度为O(n*m*q)&#xff09;解法二&#xff1a;二维前缀和&#xff08;时间复杂度为O(m*n)O(q)) 代码实现解法二&#xff1a;前缀和&#xff08;C)Java 题目描述 题目链接&#xff1a;DP35 【模板】二维…

三星电脑文件夹误删了怎么办?恢复方案在此

在使用三星电脑的过程中&#xff0c;我们可能会不小心删除了某个重要的文件夹&#xff0c;其中可能包含了工作文件、家庭照片、视频或其他珍贵的数据。面对这种突发情况&#xff0c;不必过于焦虑。本文将为您提供几种有效的恢复方案&#xff0c;希望能帮助您找回误删的文件夹及…

openEuler-22.03安装 mysql8.0.32

一、下载解压 下载地址&#xff1a; MySQL :: Download MySQL Community Server (Archived Versions) tar -xvf mysql-8.0.32-1.el7.x86_64.rpm-bundle.tar -C /opt/mysql-8.0.32 二、安装 最开始安装一直报错 缺少 libcrypto.so.10库文件,安装openssl可以解决 wget http://…

Java客户端如何直接调用es的API

Java客户端如何直接调用es的API 一. 问题二. withJson 前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 一. 问题 今天做项目的时候&#xff0c;想要直接通过java客户端调用es的api…

揭秘工业大模型:从人工智能小白到技术先锋

工业大模型的五个基本问题 信息化时代&#xff0c;数字化转型成为企业提升营运效率、应对经营风险和提升核心竞争力的重要途径。在此过程中&#xff0c;数据作为一种客观存在的资源&#xff0c;所产生的价值日益凸显。党的十九届四中全会从国家治理体系和治理能力现代化的高度将…

【万字长文】看完这篇yolov4详解,那算是真会了

前言 目标检测作为计算机视觉领域的一个核心任务&#xff0c;其目的是识别出图像中所有感兴趣的目标&#xff0c;并给出它们的类别和位置。YOLO&#xff08;You Only Look Once&#xff09;系列模型因其检测速度快、性能优异而成为该领域的明星。随着YOLOv4的推出&#xff0c;…

双塔模型在召回和粗排的区别

答案参考&#xff1a;推荐系统中&#xff0c;双塔模型用于粗排和用于召回的区别有哪些? - 知乎 召回和粗排在不同阶段面临样本不一样&#xff0c;对双塔来说样本分布差异会使召回和粗排采取不一样的方式。召回打分空间是全部item空间&#xff0c;曝光只有很少一部分&#xff0…

【机器学习】集成学习---Bagging之随机森林(RF)

【机器学习】集成学习---Bagging之随机森林&#xff08;RF&#xff09; 一、引言1. 简要介绍集成学习的概念及其在机器学习领域的重要性。2. 引出随机森林作为Bagging算法的一个典型应用。 二、随机森林原理1. Bagging算法的基本思想2. 随机森林的构造3. 随机森林的工作机制 三…

ClickHouse 如何实现数据一致性

文章目录 ReplacingMegreTree 引擎数据一致性实现方式1.ReplacingMegreTree 引擎2.ReplacingMegreTree 引擎 手动合并3.ReplacingMegreTree 引擎 FINAL 查询4.ReplacingMegreTree 引擎 标记 GroupBy5.允许偏差 前言&#xff1a;在大数据中&#xff0c;基本上所有组件都要求…

Docker创建镜像之--------------基于Dockerfile创建

目录 一、在编写 Dockerfile 时&#xff0c;有严格的格式需要遵循 二、Dockerfile 操作常用的指令 2.1ENTRYPOINT和CMD共存的情形 2.2ENTRYPOINT和CMD的区别 2.3ADD 与COPY的区别 三、Dockerfile案例 3.1构建apache镜像 3.1.1 创建镜像目录方便管理 3.1.2创建编写dock…

函数递归与迭代

目录 1.递归 1.1递归的思想 1.2递归的限制条件 2.递归与迭代 1.递归 函数递归是什么&#xff1f; 递归是学习C语⾔函数绕不开的⼀个话题&#xff0c;那什么是递归呢? 递归其实是⼀种解决问题的⽅法&#xff0c;在C语⾔中&#xff0c;递归就是函数⾃⼰调⽤⾃⼰。 写⼀个史…

大模型对数字营销的驱动赋能

一、大模型驱动的营销数智化个信未来发展趋势 1.模型算法能力全面升级 大模型凭借智能化的用户洞察&#xff0c;个性化的需求预测、系统化的数据分析、效率化的营销决策以及实实化的全域检测支持&#xff0c;为营销行业更加准确地把握市场动态和消费者需求提供了强大支持。可以…

Spring Boot 如何实现缓存预热

Spring Boot 实现缓存预热 1、使用启动监听事件实现缓存预热。2、使用 PostConstruct 注解实现缓存预热。3、使用 CommandLineRunner 或 ApplicationRunner 实现缓存预热。4、通过实现 InitializingBean 接口&#xff0c;并重写 afterPropertiesSet 方法实现缓存预热。 1、使用…

数据结构和算法:贪心

贪心算法 贪心算法是一种常见的解决优化问题的算法&#xff0c;其基本思想是在问题的每个决策阶段&#xff0c;都选择当前看起来最优的选择&#xff0c;即贪心地做出局部最优的决策&#xff0c;以期获得全局最优解。 贪心算法和动态规划都常用于解决优化问题。它们之间存在一…