JavaScript 通常会触发视觉变化。有时 直接通过样式操作进行更改,有时通过计算 更改,例如搜索数据或对数据进行排序。时机不合适或 长时间运行的 JavaScript 可能是导致性能问题的常见原因, 尽可能减少其影响。
样式计算
通过添加和移除元素、更改属性、类 或播放动画会导致浏览器重新计算元素样式, 例如网页的部分或完整布局。此过程称为 计算样式的样式。
浏览器通过创建一组匹配的选择器来开始计算样式, 确定适用于任何指定元素的类、伪选择器和 ID。 然后,它会处理来自匹配选择器的样式规则, 元素的最终样式
样式重新计算时间和互动延迟时间
Interaction to Next Paint (INP) 是一种以用户为中心的运行时 性能指标,用于评估网页对用户输入的总体响应情况。 它衡量从用户与网页互动到网页之间的互动延迟时间 而下一帧则会显示相应的视觉更新 界面
绘制下一次互动所用的时间是互动的一个重要组成部分 帧。用于呈现下一帧的渲染工作由许多部分组成, 包括计算在布局、绘制和 合成工作。本页重点介绍样式计算开销, 与互动相关的渲染阶段的一部分,也会减少其 包括样式计算在内
降低选择器的复杂性
简化选择器名称有助于加快页面样式的呈现速度 计算。最简单的选择器会引用 CSS 中只包含 课程名称:
.title {
/* styles */
}
但是,随着项目规模的扩大,它可能需要更复杂的 CSS, 选择器,如下所示:
.box:nth-last-child(-n+1) .title {
/* styles */
}
要确定这些样式如何应用于网页,浏览器必须有效地
询问“此元素是否为包含 title
类的元素,且其父项是
minus-nth-plus-1 带有 box
类的子元素?”
弄清楚这个过程可能需要很长时间,
以及相关浏览器为了简化操作,您可以更改选择器
改为一个类名称:
.final-box-title {
/* styles */
}
这些替换类名称可能看上去不协调,但确实会导致浏览器
工作量要简单得多例如,在旧版本中,浏览器知道
元素是其类型的最后一个元素,因此必须先了解所有
以确定其后面的元素是否有可能
为 nth-last-child
。这在计算上
只是因为其类匹配就将选择器与元素匹配。
减少要计算样式的元素数量
另一个性能考虑因素,通常比选择器更重要 复杂性是指当某个元素发生变化时需要完成的工作量。
一般来说,计算计算元素样式时最糟糕的开销就是 是元素数乘以选择器数,因为浏览器 每个元素至少要针对每种样式检查一次,看看它们是否 匹配。
样式计算可以直接针对少数元素,而无需失效 整个页面。在现代浏览器中,此问题一般不会那么大问题,因为 浏览器并不一定需要检查更改可能会影响的所有元素。 另一方面,旧版浏览器有时无法针对此类任务进行优化。地点 您应减少失效元素的数量。
衡量样式重新计算的开销
衡量样式重新计算开销的一个方法是使用 面板。请按以下步骤开始操作:
- 打开开发者工具。
- 前往效果标签页。
- 点击录制。
- 与网页互动。
停止录制后,您会看到如下图片:
顶部的条形是一个微型火焰图 。activity 越靠近条形底部,速度越快 哪些帧是由浏览器绘制的如果您看到火焰图逐渐平稳, 上面有红色条,则表示您 长时间运行的帧。
在滚动等互动过程中,长时间运行的帧 看看。如果您看到一个大的紫色区块,请放大该活动,然后选择任意一项 重新计算样式一文,以便详细了解 开销非常大的样式重新计算工作。
点击事件会显示其调用堆栈。如果渲染工作是由 它会调用触发样式更改的 JavaScript。 还会显示受该变化影响的元素数量 - 刚好超过 900 个 元素,以及计算样式所用的时间。您可以使用 这些信息,开始尝试在代码中查找修复方法。
使用块、元素、修饰符
诸如 BEM(块、元素、修饰符)之类的编码方法 纳入选择器匹配的性能优势。BEM 建议 所有内容都有一个类;如果需要层次结构,则应该使用层次结构 也会包含在类名称中:
.list {
/* Styles */
}
.list__list-item {
/* Styles */
}
如果您需要修饰符(如最后一个子子示例所示),可以添加修饰符, :
.list__list-item--last-child {
/* Styles */
}
BEM 是组织 CSS 的理想起点, 而这得益于它所提倡的样式查找,
如果您不喜欢 BEM,还有其他方法可以处理 CSS,但应该 在开始之前,请评估其性能和人体工学。
资源
Unstone 中的主打图片,由 Markus Spiske 制作。