拆分为 b()、e()、m() 三个独立 mixin 是最稳、最易调试的 BEM 封装方式,因其天然契合 BEM 语义层级、支持链式 & 推导、保障编译后类名可溯源,避免单 mixin 导致的参数混淆、嵌套失效与结构断裂。

直接用 @mixin b() + @mixin e() + @mixin m() 三件套,配合全局 $namespace 变量,是最稳、最易调试的封装方式。别写单个巨无霸 bem($block, $element, $modifier) ——它会让嵌套失效、语义模糊、编译后类名溯源困难。
为什么必须拆成 b()、e()、m() 三个独立 mixin
常见错误是试图用一个 mixin 覆盖所有 BEM 场景,比如:@mixin bem($block, $element: null, $modifier: null)。这会立刻踩中三个坑:
- 调用时参数顺序极易传错:
@include bem('button', 'icon')和@include bem('button', null, 'large')容易混淆,IDE 无法提示语义 - 无法表达真实嵌套关系:BEM 元素(
__)必须出现在块作用域内,但单 mixin 没有「先建块、再在其内部加元素」的结构能力 - 编译后 CSS 类名来源不可追溯:你看到
.u-button__icon,但不知道它是哪个@include产出的,调试时得反向查整个文件
而拆开后,结构天然对齐 BEM 语义:@include b(button) { @include e(icon) { ... } } → 编译即得 .u-button .u-button__icon,层级清晰,调用即所见。
@mixin b($block) 必须依赖 $namespace 和 #{$B} 插值
不能写死类名(如 .btn),否则无法跨组件复用;也不能靠 & 推导(如 #{&}__icon),否则在媒体查询或修饰符上下文中会拼出 .btn.is-active__icon 这类非法结构。
-
$namespace需提前在全局定义,例如:$namespace: 'u';,所有 BEM mixin 都基于它生成前缀 -
b()内部必须用插值:.#{$namespace + '-' + $block},而不是.u-#{$block}—— 后者把命名空间硬编码进 mixin,失去灵活性 - 务必用
@content注入样式,而非在 mixin 里写死规则,否则无法支持任意嵌套结构(比如@include b(card) { @include m(expanded) { ... } })
示例正确写法:
@mixin b($block) {
$B: $namespace + '-' + $block;
.#{$B} {
@content;
}
}
@mixin e($element) 和 @mixin m($modifier) 必须用 &,且只拼接 __ 或 --
这是最容易翻车的地方:元素和修饰符必须严格基于当前块作用域生成,不能字符串拼接,也不能用 @at-root 提升层级。
-
e()必须写成:&__#{$element} { @content; }——&代表外层块选择器,确保结果是.u-button__icon,不是孤立的.u-button__icon -
m()同理:&--#{$modifier} { @content; },禁止写成.#{$B}--#{$modifier},否则脱离上下文,破坏 BEM 层级 - 绝对不要在
e()或m()里用@at-root,它会让生成的选择器脱离父块,变成全局声明,BEM 结构瞬间断裂
错误示范:@at-root .#{$B}--#{$modifier} { @content; } → 编译出 .u-button--large 独立存在,无法与 .u-button 形成语义关联。
修饰符嵌套元素时,& 仍能正确链式展开
BEM 允许修饰符下再挂元素,比如 .u-button--large__icon。只要坚持用 &,Sass 就能自动展开为完整路径,无需额外逻辑。
- 写法自然流畅:
@include b(button) { @include m(large) { @include e(icon) { width: 20px; } } } - 编译结果准确:
.u-button--large__icon { width: 20px; },不是.u-button .u-button--large__icon(后者多了一层不必要嵌套) - 关键点在于:每次
&都指向上一层选择器字符串,所以&__icon在&--large内部,就等于.u-button--large__icon
这个能力完全依赖 & 的语义行为,一旦换成字符串拼接或 @at-root,链式展开就断了——这也是为什么所有可靠 BEM mixin 方案都强制要求用 &,而不是“看起来更直观”的字符串操作。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











