公共组件库 class 名必须带业务/团队前缀、禁用泛化词,并经工具链三阶拦截;Block 名是可交付 UI 单元的唯一 ID,须用如 nc-button 格式,禁用 base-button 等泛化命名。

公共组件库的 class 名不是“起得像 BEM”就行,而是必须带业务/团队前缀、禁用泛化词、通过工具链三阶拦截——否则三个月后就会出现 btn--primary 和 button-primary 同时生效却没人认领。
Block 名怎么定才不和 Ant Design、Element Plus 撞车
直接叫 button 或 card 是高危操作,第三方库和内部旧代码都会覆盖它。Block 名本质是「可交付 UI 单元」的唯一 ID,不是语义描述。
- ✅ 推荐格式:
nc-button(nc= your team/product initials)、ds-input(ds= design system)、dash-chart-bar - ❌ 禁用:
base-button、ui-card、common-modal——这些词在 PR 里一眼就能被识别为命名失焦 - React/Vue 组件名小写中划线化可直接映射:
UserCard.vue→ Block 名应为user-card,不是usercard或userCard
Element 命名为什么不能写成 card__content__title
__ 表达的是逻辑归属,不是 DOM 深度。出现双下划线嵌套,说明你把 wrapper div 当成了语义节点,而它很可能只是个无意义的容器。
- ✅ 正确:
card__title、card__body、card__footer——全是card的直接子元素 - ❌ 错误:
card__content__title——content不是独立 block,没有封装能力,也不复用 - 解法:删掉无意义 wrapper;或真有复用场景,才把
content提升为独立 block(如card-content)
Modifier 怎么加才不会变成“状态污染”
Modifier 描述的是「谁的状态变了」,不是「在哪被用了」。加错位置会导致样式无法收敛、调试时 DevTools 里类名和源码对不上。
立即学习“前端免费学习笔记(深入)”;
- ✅ 加在 Block 上:
nc-button--loading、ds-input--error——整个组件进入某种状态 - ✅ 加在 Element 上:
menu__item--active、form__label--required——仅该部分表现不同 - ❌ 避免:
nc-button--in-modal、card--on-mobile——这是容器约束,应由父级 wrapper 类(如modal__content)或媒体查询处理 - JS 动态拼接时别手写:
className={`nc-button nc-button--${variant}`}容易漏空格、错连字符;推荐用clsx或封装常量:cn('nc-button', { 'nc-button--disabled': isDisabled })
最常被忽略的一点:BEM 不是写完就完的事。Block 名一旦定错,后续所有 __element 和 --modifier 都跟着错;而这类错误在 CI 里不会报错,只会在半年后某个深夜上线时,突然发现 nc-button 样式被 ant-btn 覆盖了——因为当初没加前缀,也没配 stylelint-selector-bem-pattern。


















