减少样式计算的范围和复杂度

本文翻译自 Reduce the scope and complexity of style calculations,作者:Jeremy Wagner, 略有删改。

JavaScript通常用来改变页面的视觉效果。比如通过改变style样式或者通过计算后改变页面布局,比如搜索或排序数据。长时间运行的JavaScript可能是导致性能问题的常见原因,应该尽可能地减少它的影响。

样式计算

通过添加和移除元素、更改属性、类或播放动画来改变 DOM 会导致浏览器重新计算元素样式,并在许多情况下重新布局页面的部分或全部内容。这个过程称为计算样式计算。

浏览器开始计算样式,通过创建一组匹配选择器来确定哪些类、伪类和 ID 适用于任何给定元素。然后,它处理匹配选择器的样式规则,并确定元素具有哪些最终样式。

样式重新计算时间和交互延迟

Interaction to Next Paint (INP) 是一个以用户为中心的运行时性能指标,评估页面对用户输入的整体响应能力。它衡量了用户与页面交互时的延迟,直到浏览器绘制下一帧,展示相应的视觉更新给用户界面。

交互的一个重要组成部分是绘制下一帧所需的时间。用于呈现下一帧的渲染工作由许多部分组成,包括在布局、绘制和合成工作之前发生的页面样式计算。本页面侧重于样式计算成本,但减少与交互相关的渲染阶段的任何部分也会减少总延迟,包括样式计算在内。

简化选择器

简化选择器名称有助于加快页面的样式 计算。最简单的选择器在CSS中引用一个元素, 类别名称:

.title {/* styles */
}

但是,随着任何项目的增长,它可能需要更复杂的CSS, 选择器看起来像这样:

.box:nth-last-child(-n+1) .title {/* styles */
}

为了确定这些样式如何应用于页面,浏览器必须有效地询问“这是一个具有类名为 title 的元素,其父元素是具有类名为 box 的倒数第 n+1 个子元素吗?”根据所使用的选择器和具体浏览器的不同,这个过程可能需要很长时间。为了简化这个过程,您可以将选择器更改为只是一个类名:

.final-box-title {/* styles */
}

这些替代的类名可能看起来有些奇怪,但它们使浏览器的工作变得简单得多。在之前的版本中,为了知道一个元素是其类型的最后一个元素,浏览器必须首先了解所有其他元素的情况,以确定是否有任何在它之后的元素可能是倒数第 n 个子元素。这比仅仅匹配一个类名相符的元素的成本要昂贵得多。

减少设置样式的元素数量

另一个性能考虑因素,通常比选择器复杂性更重要的是当元素发生变化时需要进行的工作量。

一般来说,计算计算样式的最坏情况成本是元素数量乘以选择器数量,因为浏览器需要至少一次地将每个元素与每个样式进行匹配以查看是否匹配。

样式计算可以直接针对少数元素而不是使整个页面失效。在现代浏览器中,这往往不是一个问题,因为浏览器并不总是需要检查所有可能受到更改影响的元素。另一方面旧版浏览器并没有总是针对这类任务进行优化。在可能的情况下,您应该减少失效元素的数量。

衡量您的样式重新计算成本

衡量样式重新计算成本的一种方法是使用性能 Chrome DevTools中的面板。请执行以下操作测量:

  • 打开DevTools。
  • 切换至Performance tab。
  • 点击Record
  • 操作页面交互

最后停止录制时,您将看到类似于以下图像的内容:

顶部的条状图是一个微型火焰图,同时还绘制了每秒帧数。活动距离条状图底部越近,浏览器绘制帧的速度就越快。如果您看到火焰图在顶部水平化,并且顶部有红色条形图,那么您的工作可能导致长时间运行的帧。

像滚动这样的交互中出现长时间运行的帧值得仔细观察。如果您看到一个大的紫色块,请放大活动并选择标记为“Recalculate Style”的任何工作,以获取关于可能昂贵的样式重新计算工作的更多信息。

单击事件会显示其调用堆栈。如果渲染工作是由用户交互引起的,它会指出触发样式更改的 JavaScript。它还显示更改影响的元素数量——在这种情况下大约有 900 个元素——以及样式计算所需的时间。您可以利用这些信息开始尝试在您的代码中找到解决方案。

使用BEM

像 BEM(块、元素、修饰符)这样的编码方法内置了选择器匹配性能优势。BEM 建议所有内容都具有单个类,并且在需要层次结构时,该层次结构也会嵌入到类名中。

.list {/* Styles */
}.list__list-item {/* Styles */
}

如果您需要一个修饰符,比如在last-child示例中,您可以添加如下内容:

.list__list-item--last-child {/* Styles */
}

BEM 是优化 CSS 的良好起点,它促进了样式查找的简化。如果您不喜欢 BEM,还有其他方法来处理您的 CSS,但在开始之前,您应该评估它们的性能和效率是否满足。


看完本文如果觉得有用,记得点个赞支持,收藏起来说不定哪天就用上啦~

专注前端开发,分享前端相关技术干货,公众号:南城大前端(ID: nanchengfe)

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

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

相关文章

.NET 开发支持技术路线 .Net 7 将停止支持

.NET 开发技术路线图 微软方面强调,使用 .NET 7 的应用程序将在支持结束后继续运行,但用户可能无法获得 .NET 7 应用程序的技术支持。他们不会继续为 .NET 7 发布新的安全更新,用户可能会面临安全漏洞问题。 开发人员必须使用 .NET 8 SDK 构建…

蓝桥杯第七届大学B组详解

目录 1.煤球数量; 2.生日蜡烛; 3.凑算式 4.方格填数 5.四平方和 6.交换瓶子 7.最大比例 1.煤球数量 题目解析:可以根据题目的意思,找到规律。 1 *- 1个 2 *** 3个 3 ****** 6个 4 ********** 10个 不难发现 第…

安科瑞路灯安全用电云平台解决方案【电不起火、电不伤人】

背景介绍 近年来 ,随着城市规模的不断扩大 ,路灯事业蓬勃发展。但有的地方因为观念、技术、管理等方面不完善 ,由此引发了一系列安全问题。路灯点多面广 ,一旦漏电就极容易造成严重的人身安全事故。不仅给受害者家庭带来痛苦 &am…

计算方法实验3:反幂法求按模最小特征值及特征向量

Task Algorithm LU-Doolittle分解 A L U \mathbf{A}\mathbf{L}\mathbf{U} ALU 其中 L \mathbf{L} L为单位下三角阵, U \mathbf{U} U为上三角阵. 则 A x b \mathbf{A}\mathbf{x}\mathbf{b} Axb可化为 L U x L y b \mathbf{L}\mathbf{U}\mathbf{x}\mathbf{L}\mathbf{y}\math…

STM32的简介

内存 一般MCU包含的存储空间有FLASH和RAM,(RAM和flash又有片上和片外的区别,片上表示mcu自带的,已经封装在MCU内部的,片外表示外挂的,当项目中需要做一些复杂的应用,会存在资源不足的情况,这时…

JavaScript基础语法–变量

文章目录 认识JavaScript变量程序中变量的数据(记录)–变量变量的命名格式在Java script中变量定义包含两部分1. 变量声明(高级JS引擎接下来定义一个变量)2. 其他的写法 变量命名的规范(遵守)变量的练习a. …

RocketMQ与Spring Boot完美结合:事务消息的全面解析

生产者端 业务场景:考虑一个在线电商平台的订单支付业务场景,该场景中我们需要处理用户的支付操作并确保订单状态的更新与库存减少这两个操作要么同时成功,要么同时失败,以保证数据的一致性。我们将使用RocketMQ事务消息来实现这…

【微信】公众号开发

文章目录 概述与微信交互环境准备开发者工具 注册公众号服务器基本配置存取access_token示例代码来源 概述 不同类型公众号主要区别 与微信交互 实际上我们在公众号里的所有操作,都会发送到微信的服务器上,微信服务器将这些动作的具体含义按照一定的…

JavaScript的使用

一,JavaScript的介绍 1.1 简介 网页开发唯一可选语言 增加网页动态性与交互性 服务端开发 可以对数据库文件读写 1.2 引入 html内部使用script标签 在script在外部文件中填写 在外部文件中填写 在html内部通过script的src属性引入外部js内部直接编写js 二&…

PWM波输出-定时器输出比较单元

目录 1,前言 2,实现过程 2.1 比较部分 2.2 输出部分 1,前言 电平,作为单片机的“肌肉”,承担着实践单片机的“想法“的重要任务。而PWM波,则是电平这个大类的重中之重,可以说,没…

VUE 视图不刷新解决方法

折腾VUE总会遇到这种问题,一直以来都是想用各种方法凑合,网上一般也是方法各异,像this.$updateForce强制刷新视图(基本无效),还有用vue的set方法、js的splice方法设置数据,但这并不能解决所有问…

当代深度学习模型介绍--门控循环单元(GRUs)

AI大模型学习 方向一:AI大模型学习的理论基础 模型和应用的多样化:随着研究的深入,深度学习领域出现了多种创新的模型架构: 卷积神经网络(CNNs)专门针对图像处理任务进行了优化,通过模拟生物视…

STM32的芯片无法在线调试的情况分析

问题描述 本博客的目的在于帮助网友尽快地解决问题, 避免浪费时间, 查漏补缺。 在stm32的开发过程中,有时会遇到"STM No Target connected"的错误提示,这说明MDK开发环境无法与目标设备进行通信,导致无法烧…

YOLOv9改进策略 :注意力机制 | 注意力机制与卷积的完美融合 | 最新移动端高效网络架构 CloFormer

💡💡💡本文改进内容: 引入CloFormer 中的 AttnConv,上下文感知权重使得模型能够更好地适应输入内容。相比于局部自注意力机制,引入共享权重使得模型能够更好地处理高频信息,从而提高性能。 💡💡💡注意力机制与卷积的完美融合 AttnConv | 亲测在多个数据集能够…

15.三数之和

题目 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k ,同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。注意:答案中不可以包含重复的三元组。示例 …

windows安全中心设置@WindowsDefender@windows安全中心常用开关

文章目录 abstractwindows defender相关服务👺 停用windows Defender临时关闭实时防护使用软件工具关闭defender control(慎用)dismdControl 其他方法使其他杀毒软件注册表修改 保护历史恢复被认为是有病毒的文件添加信任目录,文件,文件类型或进程 abstract window…

算法复习:链表

链表定义 struct ListNode { int val;ListNode *next;ListNode(int x) : val(x), next(nullptr) {} }; 链表的遍历:ListNode phead; while(p!null) pp.next; 找到链表的尾结点:phead; while(p.next!null)pp.next; 链表节点的个数: phead…

java 继承extends

权限 子类会自称父类所有的非私有的成员变量和方法(不包括缺省和protected)权限修饰符的种类如下: 上面說的protected 方法可以被任意包的子类中使用,但是子类的的实例不能使用,因为没有继承,否则报错。 继…

mongodb中的字符串排序

前言 数据库有一索引字段,ObjectId与string类型混用。 需要辨明sort后的排序关系。 输入 [{"_id": {"$oid": "e98799a7e181225ad5c87476"} }, {"_id": {"$oid": "e98799a7e181225ad5c87477"} }, {&…

lab-1:Xv6 and Unix utilities

实验工具 clone实验源码 git clone git://g.csail.mit.edu/xv6-labs-2023进入目录 cd xv6-labs-2023运行内核 make qemu打印数据 Ctrl-p退出 ctrax xv6中的system call int fork() Create a process, return child’s PID. int exit(int status) Terminate the current p…