必须用btn--disabled而非btn-disabled或btn_disabled,因bem规范规定--是修饰符唯一合法分隔符,确保语义清晰、工具链可识别;后者会被误判为独立块名或无效类,导致构建时误删、devtools无法识别状态。

为什么必须用 btn--disabled 而不是 btn-disabled 或 btn_disabled
BEM 规范中,-- 是修饰符的唯一合法分隔符,它明确告诉开发者和工具链:“这是块的临时状态”,而非新组件或元素。写成 btn-disabled 会被解析为一个独立块名,DevTools 里看不出它是按钮的状态;btn_disabled 中的下划线在 BEM 里无约定含义,PurgeCSS 等构建工具可能把它当未使用类直接删掉。
常见错误现象:本地开发正常,上线后禁用样式消失——大概率是构建时误删了非 -- 命名的类。
btn--disabled 必须配合原生 disabled 属性一起用
只加 CSS 类不设 DOM 属性,键盘用户仍能聚焦、屏幕阅读器无法识别、表单提交逻辑可能绕过校验。BEM 修饰符只管视觉,disabled 属性才管语义与行为。
- 正确:
el.classList.toggle('btn--disabled', isDisabled); el.disabled = isDisabled; - 错误:
el.className += ' btn--disabled'(漏属性、易重复、难移除) - React/Vue 中注意:props 变化后要真实触发 class 更新,不能只改 state 却没映射到 class 列表
多个状态叠加时,别写组合选择器 btn--disabled.btn--loading
每个修饰符应独立声明样式,避免耦合。写 .btn--disabled.btn--loading { ... } 会导致组合爆炸、维护困难,且漏一个类就失效。
正确做法是分开定义:
.btn--disabled { opacity: 0.6; cursor: not-allowed; }
.btn--loading { cursor: wait; }
这样即使只加 btn--disabled,也能保证禁用态基础表现;JS 控制时也只需 toggle 各自类名,不用判断“当前有没有 loading”。
别把 btn--disabled 和伪类 :disabled 混着用
框架如 React 不一定把 disabled prop 同步写入 DOM 属性,:disabled 选择器常失效;而 btn--disabled 是显式可控的状态标记,SSR 友好、调试清晰、工具链可识别。
更关键的是:伪类无法表达业务意图。比如“权限不足导致禁用”和“表单未填完导致禁用”,都该用 btn--disabled,再由 JS 根据不同条件控制增删,而不是依赖 DOM 属性反射。
容易被忽略的一点:多个修饰符共存时,CSS 层叠顺序由规则书写位置和选择器权重决定,不是 HTML class 的顺序。所以不要假设 btn--disabled btn--loading 一定会让禁用样式覆盖加载样式——得看 CSS 文件里哪条规则写在后面。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











