Vue3 useCssModule在组合式API中使用CSS Modules
在 Vue3 的组合式 API 中,useCssModule 是一个非常有用的工具,它能让你方便地在 <script setup> 中访问 CSS Modules 生成的类名。本文将手把手教你如何使用它。
什么是 CSS Modules 和 useCssModule?
- CSS Modules:一种 CSS 范式,通过编译将类名转换成唯一的、作用域的标识符,从而避免不同组件间的样式冲突。它不是 Vue 独有的,而是 Webpack、Vite 等构建工具支持的一个标准。
useCssModule:一个 Vue3 的组合式 API 钩子函数。当你在组件的<style>标签上使用module属性时,useCssModule()会返回一个对象,这个对象的键是你写的原始类名,值是编译后生成的唯一类名。
如何在组合式 API 中使用 useCssModule
1. 在 <style> 标签中启用 CSS Modules
首先,你需要在你的单文件组件 (SFC) 的 <style> 标签上添加 module 属性。这是启用 CSS Modules 的关键。
<style module>
/* 在这里编写你的 CSS */
.title {
color: #42b983;
font-weight: bold;
}
.content {
padding: 20px;
}
</style>
2. 在 <script setup> 中引入并使用 useCssModule
在 <script setup> 代码块中,调用 useCssModule() 函数。它会返回一个对象,包含所有你在 <style module> 中定义的类名映射。
<script setup>
// 调用 useCssModule 获取类名映射对象
const $style = useCssModule();
// 现在,你可以像使用普通对象一样使用 $style
// 例如:$style.title, $style.content
</script>
注意:虽然你可以将返回的对象命名为任何变量名(如 cssModules),但 $style` 是一个约定俗成的命名,能清晰地表明它来自样式。
### 3. 在 `<template>` 中绑定类名
最后,在模板中使用 `v-bind` 或 `:` 将类名绑定到你的 HTML 元素上。你需要使用 `$style 对象来访问编译后的类名。
<template>
<div>
<!-- 绑定类名 -->
<h1 :class="$style.title">这是一个标题</h1>
<p :class="$style.content">这是内容段落。</p>
</div>
</template>
完整示例
下面是一个完整的 .vue 文件示例,展示了 useCssModule 的完整用法。
<template>
<div class="container">
<h1 :class="$style.title">欢迎来到我的页面</h1>
<p :class="$style.description">这是一个使用 CSS Modules 和组合式 API 的示例。</p>
<button :class="[$style.button, $style.primary]">主要按钮</button>
<button :class="[$style.button, $style.secondary]">次要按钮</button>
</div>
</template>
<script setup>
// 1. 调用 useCssModule 获取样式对象
const $style = useCssModule();
</script>
<style module>
/* 2. 编写 CSS Modules 样式 */
.container {
font-family: 'Arial', sans-serif;
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
.title {
color: #2c3e50;
text-align: center;
}
.description {
color: #7f8c8d;
line-height: 1.6;
}
.button {
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
margin-right: 10px;
}
.primary {
background-color: #3498db;
color: white;
}
.secondary {
background-color: #95a5a6;
color: white;
}
</style>
```
---
## 进阶用法与注意事项
### 动态类名
`useCssModule` 返回的对象可以无缝地与 Vue 的动态类名绑定结合使用。
```vue
<script setup>
const $style = useCssModule();
const isActive = ref(true);
// ... 其他逻辑
</script>
<template>
<div :class="[$style.box, { [$style.active]: isActive }]">
<!-- 当 isActive 为 true 时,会同时应用 $style.box 和 $style.active 类 -->
</div>
</template>
<style module>
.box {
width: 100px;
height: 100px;
background-color: #eee;
}
.active {
border: 2px solid blue;
}
</style>
自定义模块名称
如果一个组件中有多个 <style module>,你可以给它们命名,然后在 useCssModule 中传入名称来获取对应的模块。
<style module="foo">
/* foo 模块样式 */
.foo-title {
color: red;
}
</style>
<style module="bar">
/* bar 模块样式 */
.bar-title {
color: blue;
}
</style>
<script setup>
const fooStyles = useCssModule('foo');
const barStyles = useCssModule('bar');
// 使用时
// :class="fooStyles['foo-title']"
// :class="barStyles['bar-title']"
</script>
与 <style scoped> 的区别
虽然两者都能实现样式隔离,但它们的工作原理和适用场景不同。下表总结了它们的区别:
| 特性 | <style scoped> |
<style module> |
|---|---|---|
| 原理 | 通过在元素和选择器上添加唯一的 data-v-xxx 属性来实现作用域。 |
通过编译将类名重命名(例如 .title 变为 _title_1jk23)来实现作用域。 |
| 使用方式 | 在 <template> 中可以直接使用类名(如 class="title")。 |
在 <template> 中需要通过 useCssModule() 获取的映射对象来使用类名(如 :class="$style.title"`)。 |
| **标准** | Vue 特有的语法。 | Web 标准,被 Webpack、Vite 等广泛支持。 |
| **适用场景** | 适用于简单的、组件内的样式隔离,代码更简洁。 | 适用于需要更精细控制、或与其它使用 CSS Modules 的库(如 React)协作的场景。 |
你可以根据项目需求选择使用 `scoped`、`module`,或者两者结合。例如,一个组件可以同时拥有一个 `scoped` 的样式块和一个 `module` 的样式块。
### 命名约定
默认情况下,Vite 会将 CSS Modules 的类名转换为驼峰式(camelCase)。例如,`.my-class-name` 会被编译为 `$style.myClassName。 |
你可以在 Vite 配置中修改这个行为,例如改为使用下划线(kebab-case):
// vite.config.js
export default defineConfig({
css: {
modules: {
localsConvention: 'dashes' // 'camelCase' (default) or 'dashes'
}
}
})
如果设置为 'dashes',那么 .my-class-name 将被编译为 $style['my-class-name'],你需要使用方括号语法来访问。

暂无评论,快来抢沙发吧!