bem评审需严守三原则:类名必须含块名、元素用双下划线、修饰符仅表状态;禁止空格选择器、跨块组合及非原子化修饰符;须用stylelint自动校验并拦截动态拼接。

Code Review时一眼识别非BEM类名
看到类名就该立刻判断合规性,不用翻HTML或查文档。核心就三条:.title、card-title、button--primary--loading 这三类必须打回——前者缺块名,中间者少双下划线,后者修饰符嵌套。
常见错误现象:
-
.header或.btn:泛义名,没绑定具体业务块,无法定位归属 -
user-card-avatar:用连字符代替双下划线,不符合block__element结构 -
modal__close--hover:伪态不该进BEM修饰符,应写成modal__close:hover
实操建议:
- 块名必须是具象业务词:
search-form✅,form❌ - 元素名不能单独出现:
__header非法,必须是modal__header - 修饰符只描述状态:
button--disabled✅,button--in-sidebar❌(位置属于容器职责)
审查CSS选择器时警惕BEM结构破坏
BEM的原子性一旦被选择器破坏,整个模块就失去隔离能力。只要看到空格、类型选择器或跨块组合,基本就是硬伤。
常见错误现象:
-
.card .card__title:带空格的选择器,违背“命名即作用域”原则 -
form-field p:类型选择器,无法追溯样式归属,且易被全局p规则覆盖 -
header__button--submit:按钮不属于 header 块,应独立为button块
实操建议:
- 所有 BEM 类必须直接出现在 HTML 元素的
class属性中,禁止通过父级上下文推导 - 不允许
__后再接__:card__header__title❌,应拆为card__header+card__title - 修饰符必须和基础块共存:
button--primary单独出现是逻辑错误,必须是button button--primary
用stylelint自动拦截三类高危违规
人工扫类名漏检率极高,尤其三类问题几乎无法靠眼力发现:card card--featured 写在 HTML 里但 CSS 只定义了 .card--featured;card__title 出现在非 card 容器中;button--width-200px 把具体值塞进修饰符。
必须配置 stylelint-selector-bem-pattern 插件,并显式设三项参数:
-
preset: "bem":不填或填错(如"suit")会导致规则完全失效 -
componentName: "[a-z][a-zA-Z0-9]*":禁止.UserCard、.user_list、.1card -
ignoreSelectors: ["/^\.js-/"]:放过 JS 控制类,避免误报
CI 脚本中加校验命令:npx stylelint "**/*.{css,scss,less}" --max-warnings 0,否则不合规范的代码能照常合入。
审查JSX/模板中动态类名拼接
开发者最爱绕过BEM的地方:手拼字符串。这类代码在CSS文件里查不到,但实际运行时会污染BEM边界。
常见错误现象:
-
className={`card ${isFeatured ? 'card--featured' : ''}`}:字符串拼接,工具链无法校验 -
el.classList.add('card__footer'):硬编码类名,重构时无法全局搜索替换 -
button--mobile-full:把响应式逻辑塞进修饰符,而非用媒体查询包裹button--full
实操建议:
- 禁用直接解构
styles,ESLint 规则no-restricted-imports拦截import styles from './Button.module.scss' - 提供封装函数:
useButtonClasses({ size: 'lg', loading: true })返回结构化类名对象 - 所有 modifier 值必须原子化:
button--size-lg✅,button--width-200px❌
button--loading 单独存在不报错,但删掉 button 基础类后样式全崩,这种隐性耦合只有在真实 DOM 中才暴露。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











