SCSS嵌套本身不慢,慢的是编译出的深层后代选择器(如.card .header .title),浏览器从右往左匹配时DOM越深、节点越多,计算耗时越长,4层即为性能拐点;&__title未生效主因是HTML缺失基础Block类名(如仅写而漏了card),导致.card__title规则无法匹配,且&仅指向最近父选择器,空格决定编译结果(.card &__title→.card__title,.card { .title { &--large } }→.title--large),BEM要求最终CSS全为单类名以实现扁平化作用域。

SCSS嵌套本身不慢,慢的是它编译出的深层后代选择器(如 .card .header .title),浏览器匹配时从右往左逐层回溯,DOM越深、节点越多,样式计算耗时越长——4层就是性能拐点。
为什么 &__title 编译后没生效
根本不是语法错,而是 HTML 没带基础 Block 类名。&__title 编译成 .card__title,但如果你的 HTML 只写了 或漏了 card,那这条规则完全不触发。
- 必须同时存在:
…
-
&只指向最近一层父选择器:在.card { .header { &__title { } } }中,&是.header,结果是.header__title—— 直接破坏 BEM 语义 - 空格决定编译行为:
.card { .title { &--large { } } }→.title--large;.card { &__title { } }→.card__title
如何用 BEM 真正生成扁平选择器
BEM 不是“写长名字”,而是让每个类名自带作用域,避免运行时依赖祖先链。最终 CSS 必须全是单类名,否则白做。
- ✅ 正确:
+.card__title { color: red; } - ❌ 错误:
+
.card .card__title { }—— 这仍是两层嵌套,匹配开销翻倍- ⚠️ 注意:
@use不自动扁平化;混用.card &__title会产出.card .card__title,必须全量替换为&__title- 工具验证:构建后跑
grep -r "\.[a-z]\+ \.[a-z]" dist/,揪出所有残留空格选择器哪些地方还不得不嵌套?怎么安全收口
完全零嵌套不现实,但必须锁死场景和深度。真正需要嵌套的只有三类:媒体查询、伪类、主题切换——且都应约束在 Block 边界内,不超过 2 层。
- 媒体查询只嵌 1 层:
@media (min-width: 768px) { .nav__item { display: flex; } },绝不继续写.nav__item .nav__link - 伪类挂载到 BEM 类上:
.button--disabled✅,.button:disabled❌(无法 JS 切换,破 BEM 状态可控性) - 状态组合要明确优先级:
button--loading button--disabled同时存在时,谁生效?不能靠堆叠,得靠文档或工具函数(如cn('button', { 'button--loading': loading, 'button--disabled': disabled }))控制顺序 - 禁用
@extend模拟 BEM 关系——它合并选择器,破坏“单一样式来源”原则,埋下覆盖隐患
最易被忽略的一点:BEM 类名写对了,不代表选择器就扁平了。只要最终 CSS 文件里还藏着一个空格,浏览器就得回溯一次——这不是规范问题,是构建产物是否干净的问题。
- ⚠️ 注意:
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











