CSS Modules必须写在标签里,因为只有该属性才能触发Vue SFC编译器的特殊处理,识别并生成哈希类名、注入$style对象;若仅用@import或,则无法启用模块化流程,$style为空。

CSS Modules必须通过import语句显式导入,不能用@import或方式加载
为什么style module必须写在标签里
CSS Modules不是普通CSS,它依赖Vue SFC编译器的特殊处理:只有带module属性的块才会被PostCSS插件识别并生成哈希类名,同时注入$style对象到组件作用域。如果写成,这行只是普通CSS导入,不会触发模块化流程,$style为空。
-
style module标签会自动编译为类似{ primary: "primary_abc123", danger: "danger_def456" }的对象 - 不加
module属性的块,哪怕文件名含.module.css,也不会启用CSS Modules - Vite和Vue CLI都要求
module属性作为开关,不是靠文件后缀推断
import语句与$style对象的对应关系
两种导入方式效果一致,但适用场景不同:
- 默认导入:
import styles from './Button.module.css'→ 模板中用:class="styles.primary"或class="{{ styles.primary }}" - 解构导入:
import { primary, large } from './Button.module.css'→ 直接用:class="primary",更简洁但TypeScript类型推导稍弱 - 不能混用:
import styles, { primary } from './Button.module.css'会报错,ESM不支持默认+命名混合导入
常见错误:动态拼接类名失败
这是新手最高频的坑——以为能像普通CSS那样字符串拼接,结果得到undefined:
<button :class="`btn-${type}`"></button>
// ❌ type = 'primary' → class="btn-primary",但CSS Modules中没有btn-primary这个key
// ✅ 正确写法是 styles[`btn${type}`] 或解构后直接用 primary
- CSS Modules的类名是静态编译的,运行时不存在
btn-primary这个键,只有btnPrimary或btn_primary_xxx这类生成名 - 若必须动态,优先用
Object.keys(styles).find(key => key.includes(type)),但性能差,建议提前枚举好所有合法值 - 更稳妥的做法是用
v-bind:class对象语法::class="{ [styles.primary]: type === 'primary', [styles.danger]: type === 'danger' }"
真正容易被忽略的是:CSS Modules的哈希名在开发和生产环境可能不同,所以任何硬编码哈希值(比如在测试中写死primary_abc123)都会失效。要测样式,应该测styles.primary是否非空,而不是测具体字符串内容。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











