css modules 中 styles['button__icon'] 为 undefined 的根本原因是文件名、css 类名、jsx 访问键三者未严格对齐:文件名须 pascalcase 且与组件同名(如 button.module.css),css 类须以 .button 开头(如 .button__icon),jsx 中须用小写字符串访问(styles['button__icon'])。

有必要,而且不是“可选”,是协作规模超过 3 个组件时的刚性需求。
styles['button__icon'] 为什么总是 undefined
这不是 BEM 写错了,也不是 CSS Modules 配置漏了,而是文件名、类名、JSX 访问键三者没对齐——这是唯一且必须满足的前提。
- 文件名必须 PascalCase 且与组件名严格一致:
Button.module.css✅,button.module.css或MyButton.module.css❌ - CSS 文件中只能声明以
.button开头的类:.button、.button__icon、.button--primary✅;.btn__icon或.button-icon❌ - JSX 中必须用字符串访问:
styles['button__icon']✅;styles.button__icon语法报错,styles['Button__icon']大小写不匹配也返回undefined
不用 BEM 的 CSS Modules 项目长什么样
开发时看着清爽,上线后调试抓狂:所有 .title、.content、.header 都在不同模块里重复出现,DevTools 里看到 Card_title_abc123 和 Header_title_def456,但没人知道哪个对应哪块 UI,更没法快速定位源码。
- 新人打开
index.module.css,第一反应是“这到底渲染啥?”——文件名、类名、DOM 结构三者之间没映射关系 - 重构时不敢删样式:一个
.active可能同时被导航、下拉菜单、标签页复用,但类名本身不携带归属信息 - 搜索
grep -r "\.title" src/返回 17 个结果,还得逐个点开确认作用域
localIdentName 配得太“可读”反而掩盖问题
默认哈希名(如 Button_button__abc123)把原始语义藏掉了,但配成 [name]__[local] 又会让错误静默:比如误写了 .btn__icon,编译后变成 Button__btn__icon,看起来像模像样,实际根本没生效。
- 推荐配置:
localIdentName=[name]__[local]___[hash:base64:5],产出Button__button___abc123,一眼能定位到文件和类名 - 禁止全局开启
modules: true:否则reset.css、antd.css全被模块化,样式全乱套 - TypeScript 项目必须加
declare module '*.module.css',否则import styles from './Button.module.css'直接类型报错
BEM 的 __ 和 -- 是人定的契约,CSS Modules 的哈希是机器生成的保障——前者松动一寸,后者就兜不住。最常被忽略的不是怎么写,而是“谁来 enforce”:没有 CI 检查 grep -r "\.[a-z]\+ \.[a-z]" src/,嵌套选择器就会悄悄复活;没有目录约束,components/Button/Button.module.css 里就可能出现 .header 这种脱离上下文的类名。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











