直接用classlist.toggle更安全,因classname='...'会覆盖所有已有类名,导致动画库、框架注入类丢失;而toggle等方法原子操作、自动去重、不破坏其他状态。

直接用 element.classList.toggle 控制多个 Modifier 类名,比拼字符串、条件三元或硬编码组合更安全、可维护。
为什么 className = 'btn--primary btn--disabled' 是危险操作
它会清空元素上所有已有类名,包括可能由其他模块、动画库或框架注入的类(比如 is-animating 或 ng-star-inserted)。一旦 JS 逻辑稍有改动,比如漏加一个状态,整个类名链就断了,样式回归默认,且难以定位。
- 应始终使用
classList.add()/classList.remove()/classList.toggle()操作单个类名 - 避免在模板里写
class="btn {{ isPrimary ? 'btn--primary' : '' }} {{ isDisabled ? 'btn--disabled' : '' }}"—— 空格易错、语义难读、无法复用 - React/Vue 中推荐绑定对象形式:
{'btn--primary': isPrimary, 'btn--disabled': isDisabled},但底层仍依赖 classList 行为
多状态共存时,CSS 规则怎么写才不互相覆盖
BEM 不自动合并修饰符效果。比如 .btn--primary 设背景色,.btn--disabled 设透明度和禁用交互,两者同时存在时,若没显式定义组合规则,.btn--disabled 的 pointer-events: none 可能被 .btn--primary 的 hover 样式意外绕过。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 必须显式声明组合态样式:
.btn--primary.btn--disabled { opacity: 0.4; } - 禁止写
.btn--primary--disabled—— 这是非法 BEM,语义断裂,且无法与.btn--loading自由组合 - 若组合态逻辑复杂(如 loading + disabled + compact 同时出现),建议用 CSS 自定义属性接管部分样式分支:
.btn--disabled { --btn-opacity: 0.4; },再在元素中opacity: var(--btn-opacity);
JS 添加类名后样式没生效?优先检查这三处
不是 BEM 写错了,而是类名根本没进 DOM,或进了但被覆盖/删掉。
- 检查 DevTools Elements 面板,确认目标元素的
class属性里真实存在btn--disabled,而不是is-disabled或btn-disabled拼写错误 - 构建工具(如 PurgeCSS)可能把动态添加的修饰符当“未使用”删掉,需在
safelist中显式保留正则:/btn--(primary|disabled|loading)/ - CSS 规则权重不足或被覆盖:比如写了
.btn--disabled { opacity: 0.5; },但父级有.modal .btn { opacity: 1; },后者因层级更深而胜出 —— BEM 修饰符本意就是扁平权重,别依赖嵌套选择器
真正容易被忽略的是:Modifier 类名是否在组件生命周期内被及时清理。比如异步加载中加了 btn--loading,但请求失败后忘记 remove,按钮就永远转着圈。这类问题不会报错,但用户感知极差。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










