当前位置: 首页 > news >正文

前端知识速记:重绘和回流

前端知识速记:重绘和回流

一、什么是重绘与回流

1. 重绘(Repaint)

重绘是指当元素的外观发生变化时,浏览器需要重新绘制这些元素。由于这些操作不会改变元素占据的空间,因此不需要进行回流。常见的重绘操作包括:

  • 元素的颜色、背景色、边框等样式属性发生变化
  • 元素的可见性发生变化(如 display: none 变为 display: block ps:针对这个例子也会触发回流,并且是先触发回流,再触发重绘)
    • 回流(Reflow)display: none 的元素不会在页面中占据空间,也不会参与布局计算。当将其改为 display: block 时,元素会重新出现在页面中并占据空间,这使得浏览器需要重新计算该元素以及可能受其影响的其他元素的布局信息,确定它们在页面上的位置和大小,这个重新计算布局的过程就是回流。
    • 重绘(Repaint) :在完成回流,确定好元素新的布局信息后,浏览器需要根据新的样式和布局将元素绘制到屏幕上,更新元素的外观,这个过程就是重绘。

感谢 lijibing 大佬指出问题

- 字体样式等

2. 回流(Reflow)

回流(也称为布局重排)是指当元素的尺寸、位置或其他影响其布局的属性发生变化时,浏览器需要重新计算元素的布局,并重新构建渲染树(Render Tree)的过程。在回流发生时,涉及到的元素及其后代会被重新计算并绘制,这通常会导致性能下降。常见的回流操作包括:

  • 更改元素的尺寸(如设置 widthheightpaddingbordermargin)。
  • 添加或删除可见的DOM元素(包括添加或删除元素)。
  • 修改元素的内容(如文本变化、数量,图片数量、大小、字体大小)。
  • 改变视口(如窗口缩放、滚动等)。
  • 页面初始渲染。
  • 浏览器窗口大小改变。
  • 激活CSS伪类(如 :hover)。
  • 查询某些属性或调用某些方法(如 offsetWidthscrollTop 等时会引发回流)。

值得注意的是,回流一定会引起重绘,但重绘不一定会导致回流。
例如,当你改变一个元素的颜色时,浏览器只会进行重绘操作;但是当你改变一个元素的宽度时,浏览器会进行回流操作。

二、回流的影响范围

回流的影响范围可分为全局和局部。全局回流会影响整个页面的布局,导致重新计算所有元素的样式和位置;而局部回流只会影响某些特定元素及其后代。

回流的成本通常比重绘大得多,因此我们应该尽量减少回流操作,以降低页面性能消耗。

三、如何优化回流

要提高性能,我们需要减少回流的发生频率,特别是控制回流的次数和影响范围。以下是几种有效的优化方案:

1. 减少回流次数

核心观念是尽量集中样式修改,避免频繁操作DOM。

  • 样式集中处理:将样式的修改集中到一个步骤中,而不是逐个修改。这可以通过创建一个样式数组,通过更改一个元素的 class 来实现样式的切换,从而减少操作次数。
// 1. 不集中处理样式(直接修改样式属性)
document.getElementById("update").addEventListener("click", () => {const boxes = document.querySelectorAll(".box");boxes.forEach((box) => {box.style.width = "200px"; // 直接修改样式属性box.style.height = "200px";box.style.backgroundColor = "red";box.style.transform = "translateX(50px)";});
});// 1. 减少回流次数:通过集中处理样式
document.getElementById("update").addEventListener("click", () => {const boxes = document.querySelectorAll(".box");boxes.forEach((box) => {box.classList.add("new-style"); // 通过添加类名来集中更新样式});
});
  • 通过变量存储调用 offsetWidth 结果:当需要多次获取元素的布局信息(如 offsetWidth),应将其存储在变量中以避免重复计算,从而减少回流。
// 2. 不使用变量存储 `offsetWidth` 结果(多次调用 `offsetWidth`)
document.getElementById("addBox").addEventListener("click", () => {const container = document.getElementById("container");console.log("Container Width:", container.offsetWidth); // 多次调用 offsetWidthconsole.log("Container Width:", container.offsetWidth); // 多次调用 offsetWidthconsole.log("Container Width:", container.offsetWidth); // 多次调用 offsetWidthconst newBox = document.createElement("div");newBox.className = "box new-style";container.appendChild(newBox);
});// 2. 使用变量存储调用 offsetWidth 结果:避免重复计算  
const container = document.getElementById('container');  
const containerWidth = container.offsetWidth;  // 只计算一次  
console.log('Container Width:', containerWidth); // 输出容器宽度 

2. 减少回流范围

核心观念是通过精简涉及回流的DOM操作来减小影响范围。常见减少回流范围的操作包括:

  • DOM离线操作:在进行多次DOM更新时,可以使用文档片段(DocumentFragment)来批量更新DOM,避免频繁的回流。
// 3. DOM 离线操作:使用文档片段添加多个元素  
document.getElementById('addBox').addEventListener('click', () => {  const fragment = document.createDocumentFragment();  const newBox = document.createElement('div');  newBox.className = 'box new-style'; // 直接添加样式类  fragment.appendChild(newBox);  // 一次性添加,避免多次回流  container.appendChild(fragment);  
});// 3. 不使用文档片段(直接添加元素到 DOM)
document.getElementById("addBox").addEventListener("click", () => {const container = document.getElementById("container");const newBox = document.createElement("div");newBox.className = "box new-style";container.appendChild(newBox); // 直接添加元素到 DOMconst newBox2 = document.createElement("div");newBox2.className = "box new-style";container.appendChild(newBox2); // 直接添加元素到 DOMconst newBox3 = document.createElement("div");newBox3.className = "box new-style";container.appendChild(newBox3); // 直接添加元素到 DOM
});
  • 脱离文档流:对于一些大型操作,使用绝对定位或固定定位可以将元素脱离文档流,从而减少回流的影响。
// 4. 不脱离文档流(使用默认的文档流布局)
const floatingBox = document.createElement("div");
floatingBox.className = "box";
floatingBox.style.top = "150px"; // 位置
floatingBox.style.left = "150px"; // 位置
document.body.appendChild(floatingBox); // 直接添加到文档中,不脱离文档流 // 4. 脱离文档流:使用绝对定位可减少回流影响  
const floatingBox = document.createElement('div');  
floatingBox.className = 'box';  
floatingBox.style.position = 'absolute'; // 脱离文档流  
floatingBox.style.top = '150px'; // 位置  
floatingBox.style.left = '150px'; // 位置  
document.body.appendChild(floatingBox); // 直接添加到文档中  

相关文章:

前端知识速记:重绘和回流

前端知识速记:重绘和回流 一、什么是重绘与回流 1. 重绘(Repaint) 重绘是指当元素的外观发生变化时,浏览器需要重新绘制这些元素。由于这些操作不会改变元素占据的空间,因此不需要进行回流。常见的重绘操作包括&…...

webrtc peerconnection_client peerconnection_server 连接失败问题解决 win10 win11

0 常见问题 (1) webrtc peerconnection_client 连接 peerconnection_server 无连接列表 (2)连接导致崩溃debug状态下因为这个断言 RTC_DCHECK_RUN_ON(&capture_checker_); 1 在 peerconnection\client\main.cc 当中 定义类 class CustomSock…...

【C++】STL——list的使用与底层实现

目录 💕1.带头双向链表List 💕2.list用法介绍 💕3.list的初始化 💕4.size函数与resize函数 💕5.empty函数 💕6.front函数与back函数 💕7.push_front,push_back,pop_front,pop_back函数…...

iOS 音频录制、播放与格式转换

iOS 音频录制、播放与格式转换:基于 AVFoundation 和 FFmpegKit 的实现 在 iOS 开发中,音频处理是一个非常常见的需求,比如录音、播放音频、音频格式转换等。本文将详细解读一段基于 AVFoundation 和 FFmpegKit 的代码,展示如何实现音频录制、播放以及 PCM 和 AAC 格式之间…...

【PyTorch】解决Boolean value of Tensor with more than one value is ambiguous报错

理解并避免 PyTorch 中的 “Boolean value of Tensor with more than one value is ambiguous” 错误 在深度学习和数据科学领域,PyTorch 是一个强大的工具,它允许我们以直观和灵活的方式处理张量(Tensor)。然而,即使…...

Jsoup库具体怎么用?

Jsoup 是一个非常强大的 Java 库,用于解析和操作 HTML 文档。它提供了丰富的功能,包括发送 HTTP 请求、解析 HTML 内容、提取数据、修改 HTML 元素等。以下将详细介绍 Jsoup 的基本用法和一些高级功能,帮助你更好地使用 Jsoup 进行网络爬虫开…...

python:如何播放 .spx 声音文件

.spx 是 Speex音频编解码器的文件扩展名,它是一种开源的、免费的音频编解码器,主要用于语音压缩和语音通信领域。spx 文件通常用于语音记录、VoIP应用、语音信箱等场景。 .mp3 是一种广泛使用的音频格式,它采用了有损压缩算法,可…...

HTML学习笔记(6)

利用dom操作实现&#xff0c;对一个表格的增删改查 代码如下&#xff1a; todolist.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, …...

走向基于大语言模型的新一代推荐系统:综述与展望

HightLight 论文题目&#xff1a;Towards Next-Generation LLM-based Recommender Systems: A Survey and Beyond作者机构&#xff1a;吉林大学、香港理工大学、悉尼科技大学、Meta AI论文地址&#xff1a; https://arxiv.org/abs/2410.1974 基于大语言模型的下一代推荐系统&…...

【DeepSeek-R1 +1.5B】2060显卡ollama本地部署+open-webui界面使用

https://github.com/open-webui/open-webui Deepseek开源R1系列模型&#xff0c;纯RL助力推理能力大跃升&#xff01; 2060显卡下使用deepseek-r1-1.5B deepseek开源小模型需要的显存&#xff08;根据显存来选模型大小&#xff09; &#xff0c;图from: DeepSeek本地部署&…...

《翻转组件库之发布》

背景 继《翻转组件库之打包》_杨晓风-linda的博客-CSDN博客之后&#xff0c;组件库已经可以正常构建&#xff0c;那如何像elementUI等组件库那样&#xff0c;用npm安装&#xff0c;按照既定的用法使用即可呢&#xff1f;本篇便为你揭晓 资料相关 1、npm官方文档&#xff1a;…...

在深度学习中,样本不均衡问题是一个常见的挑战,尤其是在你的老虎机任务中,某些的中奖倍数较高

在深度学习中,样本不均衡问题是一个常见的挑战,尤其是在你的老虎机任务中,某些的中奖倍数较高 在深度学习中,样本不均衡问题是一个常见的挑战,尤其是在你的老虎机任务中,某些的中奖倍数较高而其他的中奖倍数较低。这种不均衡会导致模型偏向于高频样本(低中奖倍数的),…...

语言月赛 202311【基因】题解(AC)

》》》点我查看「视频」详解》》》 [语言月赛 202311] 基因 题目描述 有一个长度为 n n n 的字符串 S S S。其只包含有大写字母。 小 A 将 S S S 进行翻转后&#xff0c;得到另一个字符串 S ′ S S′。两个字符串 S S S 与 S ′ S S′ 对应配对。例如说&#xff0c;对…...

unity学习26:用Input接口去监测: 鼠标,键盘,虚拟轴,虚拟按键

目录 1 用Input接口去监测&#xff1a;鼠标&#xff0c;键盘&#xff0c;虚拟轴&#xff0c;虚拟按键 2 鼠标 MouseButton 事件 2.1 鼠标的基本操作 2.2 测试代码 2.3 测试情况 3 键盘Key事件 3.1 键盘的枚举方式 3.2 测试代码同上 3.3 测试代码同上 3.4 测试结果 4…...

GB/T 43698-2024 《网络安全技术 软件供应链安全要求》标准解读

一、43698-2024标准图解 https://mmbiz.qpic.cn/sz_mmbiz_png/rwcfRwCticvgeBPR8TWIPywUP8nGp4IMFwwrxAHMZ9Enfp3wibNxnfichT5zs7rh2FxTZWMxz0je9TZSqQ0lNZ7lQ/640?wx_fmtpng&fromappmsg 标准在线预览&#xff1a; 国家标准|GB/T 43698-2024 相关标准&#xff1a; &a…...

ASP.NET Core与EF Core的集成

目录 分层项目中EF Core的用法 数据库的配置 数据库迁移 步骤汇总 注意&#xff1a; 批量注册上下文 分层项目中EF Core的用法 创建一个.NET类库项目BooksEFCore&#xff0c;放实体等类。NuGet&#xff1a;Microsoft.EntityFrameworkCore.RelationalBooksEFCore中增加实…...

【AI大模型】Ubuntu18.04安装deepseek-r1模型+服务器部署+内网访问

以下内容主要参考博文&#xff1a;DeepSeek火爆全网&#xff0c;官网宕机&#xff1f;本地部署一个随便玩「LLM探索」 - 程序设计实验室 - 博客园 安装 ollama Download Ollama on Linux curl -fsSL https://ollama.com/install.sh | sh 配置 ollama 监听地址 ollama 安装后…...

SpringAI系列 - 使用LangGPT编写高质量的Prompt

目录 一、LangGPT —— 人人都可编写高质量 Prompt二、快速上手2.1 诗人 三、Role 模板3.1 Role 模板3.2 Role 模板使用步骤3.3 更多例子 四、高级用法4.1 变量4.2 命令4.3 Reminder4.4 条件语句4.5 Json or Yaml 方便程序开发 一、LangGPT —— 人人都可编写高质量 Prompt La…...

Github - 记录一次对“不小心包含了密码的PR”的修复

Github - 记录一次对“不小心包含了密码的PR”的修复 前言 和好朋友一起开发一个字节跳动青训营抖音电商后端(now private)的项目&#xff0c;某大佬不小心把本地一密码commit上去并提了PR。 PR一旦发出则无法被删除&#xff0c;且其包含的commit也能被所有能看到这个仓库的…...

【玩转 Postman 接口测试与开发2_014】第11章:测试现成的 API 接口(下)——自动化接口测试脚本实战演练 + 测试集合共享

《API Testing and Development with Postman》最新第二版封面 文章目录 3 接口自动化测试实战3.1 测试环境的改造3.2 对列表查询接口的测试3.3 对查询单个实例的测试3.4 对新增接口的测试3.5 对修改接口的测试3.6 对删除接口的测试 4 测试集合的共享操作4.1 分享 Postman 集合…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数&#xff0c;对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...