唯一靠谱写法是&+参数化mixin,因@{block}__@{element}等字符串拼接丢失上下文、污染作用域、无法响应状态;而&__element能精准绑定当前块并支持伪类与extend。

直接用 & 嵌套 + 参数化 mixin 是唯一靠谱的写法,其他字符串拼接、函数返回选择器、纯变量组装都会破坏 BEM 的作用域约束或产出非法类名。
为什么不能用 @{block}__@{element} 直接拼接选择器
Less 中 @{block}__@{element} 是独立字符串表达式,它不继承当前上下文。写在 .card { } 里,编译后是 .card__header 平级规则,而不是 .card .card__header —— 看似对,实则丢失了块级作用域隔离能力。更危险的是:多个 block 共用 header 元素时,样式会互相污染。
- 漏掉
&就变成后代选择器(如.card __header→.card __header,空格无效但编译不报错) -
@{block}__@{element}无法响应父级伪类状态(比如.card:hover &__icon会失效) - 无法配合
extend或selector()做进一步抽象
如何用 & + 参数 mixin 正确封装 bem-element
核心是让 mixin 只扩展当前作用域,不生成新选择器层级。所有逻辑必须基于 & 展开:
Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。
.bem-element(@element) when (isstring(@element)) {
&__@{element} {
@content;
}
}
.card {
// 此处 & 指向 .card
.bem-element(header) {
padding: 1rem;
}
.bem-element(footer) {
margin-top: auto;
}
}
- 必须加
when (isstring(@element))防止空值编译出.card__这种非法类名 -
@content让调用方自由写样式,比固定属性 mixin 更灵活 - 不推荐把
&__@{element}包进.bem()外层 wrapper,那会导致嵌套过深、难以调试
修饰符(modifier)怎么避免重复定义
全局统一的 modifier(如 --disabled、--loading)不该每个 block 都重写一遍 &--disabled。抽成独立 mixin,用 & 绑定上下文:
.bem-modifier(@mod) when (isstring(@mod)) {
&--@{mod} {
@content;
}
}
.button {
.bem-modifier(primary) { background: #007bff; }
.bem-modifier(disabled) { opacity: 0.5; cursor: not-allowed; }
}
.input {
.bem-modifier(error) { border-color: #dc3545; }
}
- 每个 block 调用时,
&自动指向当前块,无需传入@block参数 - 禁止在
.bem-modifier内部再嵌套&__element—— BEM 不允许block--mod__element这种混合结构 - 若 modifier 需要同时作用于 block 和其某个 element,应分别调用,而非试图在一个 mixin 里合并逻辑
真正难的不是写出能编译的 BEM mixin,而是让团队所有人写 .card { .bem-element(header) { ... } } 时,心里清楚 & 此刻绑定的是哪个块 —— 这要求所有组件入口必须以单一 class 开头,且禁止跨 block 嵌套调用。否则,& 的指向会悄无声息地漂移。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










