bem 中 block-name 和 block__name 不能混用,因双下划线是语法锚点,工具链依赖它识别 element 层级;混用会导致样式脱离组件作用域、lint 无法校验、协作混乱。

为什么block-name和block__name不能混用
BEM 的双下划线 __ 是语法锚点,不是视觉分隔符。工具链(如 postcss-bem-linter、VS Code BEM 插件、构建时 CSS 提取逻辑)靠它识别 element 层级。写成 block-name 会被当做一个全新 block,而不是 block 的子元素——结果是 lint 不报错、样式不被归入组件作用域、协作时没人知道它属于哪个模块。
如何一眼识别文件中是否混用了 block-name
打开编译后生成的 CSS 文件(比如 dist/static/css/*.css),搜索当前 block 名(如 card),看所有匹配项是否都带 __ 或 --。如果出现 .card-header 或 .card-title 这类单连字符写法,说明已混用。
- 开发期配置
localIdentName=[name]__[local]___[hash:base64:5],能从哈希前缀反推来源:比如Card__title___abc12是合法的,Card__header___def34也是,但Card-header___xyz78就是非法混用 - 运行
npx postcss-bem-linter --config .bemrc Card.module.css,它会直接指出card-header不符合block__element模式
React 中怎么防止手写类名时漏掉 __
禁止在 JSX 里直接拼字符串类名。哪怕只写一次 className="card-header",就等于绕过整个 BEM 约束体系。
- 必须用
bem()工厂函数封装 block 名:const cardBem = bem('card') - 所有 element 必须走
cardBem.e('header'),所有 modifier 走cardBem.m('loading') - 传给
classnames或clsx的值,只能是styles[cardBem.e('header')]这种形式,绝不能是styles['card-header']或字面量'card-header' - 在 TypeScript 中可加一层类型守卫:让
bem('card').e只接受预定义的'header' | 'footer' | 'body'字符串
微前端场景下 block 名要不要加应用前缀
要,而且必须加。不加前缀的 card__header 在多个子应用共存时,等同于裸奔。
- block 名应为
order-mgmt__card、user-center__avatar,而不是泛化的card__header - 前缀不能硬编码,需从微前端运行时环境读取:
window.__MICRO_APP_NAME__ || 'unknown',或通过 qiankun 的props.name - CSS Modules 文件名也得同步改:不是
Card.module.css,而是OrderMgmtCard.module.css,否则styles['order-mgmt__card']查不到
block__element 当作“好看一点的 class 名”来用——它本质是一条结构契约。一旦有人写了个 card-header,后续所有人就默认这个元素可以脱离 card 存在,BEM 的边界就塌了。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











