必须通过 styles 对象访问 CSS Modules 类名,如 styles.primary 或 styles['theme-dark'],直接拼字符串无效;所有动态类名需提前定义在 .module.css 中,推荐用映射对象管理状态类并加兜底。

直接用 styles 对象取值,别拼字符串
CSS Modules 编译后会把 .primary 变成类似 Button_primary__abc123 的哈希名,这些名字只在 JS 模块里作为 styles.primary 存在。写 className="button " + (variant === 'primary' ? 'primary' : 'danger') 完全无效——因为 'primary' 不是真实类名,只是原始 CSS 文件里的标识符。
必须通过 styles 对象访问,且所有要切换的类名(如 primary、danger、large)都得提前定义在 .module.css 文件中。
-
styles.base是基础类,必选 -
styles[variant]是动态键访问,要求variant值必须和 CSS 中定义的类名完全一致(大小写、连字符) - 连字符类名(如
.theme-dark)不能用点语法,得写成styles['theme-dark']
用 classnames 合并多个动态类名
classnames 本身不关心类名来源,只负责拼接字符串。关键是你传给它的每个参数,都得是 styles.xxx 这种已解析的真实类名。
示例:
立即学习“前端免费学习笔记(深入)”;
import styles from './Button.module.css';
import cx from 'classnames';
function Button({ variant = 'primary', size = 'md', isActive }) {
return (
<button className={cx(
styles.base,
styles[variant], // ✅ 必须确保 variant 值在 CSS 中有对应类
{ [styles.active]: isActive }, // ✅ 条件为真才加 styles.active
size === 'lg' && styles.large // ✅ 布尔表达式写法
)}>
Click me
</button>
);
}
-
styles[variant]如果variant值不存在(比如传了'warning'但 CSS 里没.warning),结果是undefined,classnames会跳过它——样式丢失但不报错 - 建议加运行时校验,或用
defaultProps兜底,避免静默失败
主题类也得走 styles,别用 :global
想切深色/浅色主题?别把 .theme-dark 写死在 JSX 里,也别用 :global(.theme-dark) 提到全局——这会污染其他组件,失去模块隔离意义。
正确做法:
- 把主题类(如
.theme-dark、.theme-light)定义在同一个 CSS Modules 文件里,然后用styles['theme-dark']访问 - 或者拆成独立文件:
theme-dark.module.css和theme-light.module.css,运行时按需import()(Vite)或require()(Webpack) - 如果用
data-theme+ CSS 变量,CSS Modules 只管结构类名,变量定义放顶层,JS 控制document.documentElement.setAttribute('data-theme', 'dark')
映射对象比 if/else 更安全可维护
当状态值较多(如支付状态:pending / success / failed / cancelled),硬写三元或 if/else 易出错、难扩展。
推荐用静态映射对象:
const STATUS_CLASS_MAP = {
pending: styles.statusPending,
success: styles.statusSuccess,
failed: styles.statusFailed,
cancelled: styles.statusCancelled,
};
// 使用
<div className={cx(styles.badge, STATUS_CLASS_MAP[status] || styles.statusUnknown)}>
{status}
</div>
- 映射对象集中管理,增删状态只需改一处
- 避免
undefined导致类名缺失,|| styles.statusUnknown提供兜底 - 注意:所有 key(如
'pending')必须和后端返回或业务逻辑中的值严格一致(包括大小写、空格、下划线)
styles 对象直接操作字符串,就等于主动放弃模块性,后续调试、复用、主题切换都会卡在第一步。


















