&不可靠,仅字符串拼接;可靠bem封装需显式传块名、隔离命名空间与分隔符。因&绑定最近父选择器且不感知语义,混入中无参element易产出.card.is-active__item等非法类名,跨文件复用时上下文失控。

直接用 & 拼接 BEM 类名不可靠,& 只展开最近父选择器,不感知语义层级;真正可复用、可维护的 BEM 封装必须显式传入块名,并隔离命名空间、分隔符等配置。
为什么不能依赖 & 在 @mixin 里生成 BEM 类名
常见错误是写一个无参 @mixin element,然后在嵌套中用 &__item —— 这看似能编译出 .card__item,但一旦父选择器本身带条件(如 .card.is-active),& 就会把整个链带进来,产出 .card.is-active__item,这违反 BEM 规范(修饰符只能作用于块或元素自身)。更隐蔽的问题是:混入若被多次调用、跨文件复用,& 的上下文完全不可控。
关键点:
-
&是 Sass 编译时的字符串拼接操作符,不是 BEM 语义解析器 - 混入内部若没显式接收
$block,就无法支持组件库中动态块名(如$c-button) - 不传参的
@mixin无法与命名空间(如n-)、分隔符(__)解耦,硬编码后难以统一替换
怎样设计带命名空间和分隔符的 @mixin bem
核心是把 BEM 的结构要素拆成可配置变量,再通过参数驱动生成逻辑。推荐在 config.scss 中统一定义:
$namespace: 'n'; $element-separator: '__'; $modifier-separator: '--'; $state-prefix: 'is-';
然后在 bem.scss 中封装主混入:
@mixin bem($block) {
$B: $namespace + '-' + $block;
.#{$B} {
@content;
@mixin element($name) {
&__#{$name} { @content; }
}
@mixin modifier($name) {
&--#{$name} { @content; }
}
@mixin state($name) {
&.#{$state-prefix}#{$name} { @content; }
}
}
}
调用时必须显式传块名:
@include bem('button') {
padding: 0.5rem 1rem;
@include element('icon') {
margin-right: 0.25rem;
}
@include modifier('large') {
padding: 0.75rem 1.5rem;
}
}
哪些地方容易踩坑
即使用了上述封装,仍常因细节失控导致输出异常:
-
@content内部不能再用普通嵌套(如.icon { ... }),否则生成的是后代选择器,破坏 BEM 扁平结构 -
@include element和@include modifier必须在@content块内调用,不能提级到混入外——否则&绑定失效 - 禁止在媒体查询或伪类中嵌套
@include element,比如@media (max-width: 768px) { @include element('label') { ... } }会丢失&上下文,应改用@at-root提升 - 多个修饰符共存(如
button--primary.button--disabled)不能靠&--primary--disabled合并,必须分开声明,否则语义错乱且浏览器忽略非法类名
是否需要搭配 @function bem() 动态生成类名
纯混入方案适合大多数组件样式编写,但当你需要在属性值、动画类、JS 交互类名拼接等场景下生成 BEM 字符串时,混入就不够用了——这时必须补一个函数:
@function bem($block, $element: null, $modifier: null) {
$result: $namespace + '-' + $block;
@if $element { $result: $result + $element-separator + $element; }
@if $modifier { $result: $result + $modifier-separator + $modifier; }
@return $result;
}
用法示例:
.#{$block} {
&__title {
&::before {
content: '#{bem($block, "icon", "filled")}';
}
}
}
注意:bem() 函数只返回字符串,不能替代混入的嵌套能力;它存在的唯一理由,是让类名生成逻辑可被 JS、HTML 模板、测试断言等非 CSS 环境复用。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











