在 Vue3 项目中希望使用 SCSS 来提升样式代码的可维护性和开发效率,但配置方式与高级用法容易混淆。这篇就来聊清楚 Vue3 集成 SCSS 的完整流程、常见场景和进阶技巧。
- 安装与基础配置:不同构建工具下的依赖安装与配置步骤
- 全局变量与混合器:如何共享变量与 mixin,避免重复定义
- 高级用法:样式模块化、深度选择器、响应式 mixin
一、使用场景
- 需要使用 CSS 变量和主题切换功能
- 大型项目中的样式模块化管理
- 需要复用样式代码(mixins、继承)
- 复杂的样式逻辑处理
二、注意事项
- 需要安装相应的 SCSS 编译器依赖(
sass+sass-loader) - 不同构建工具(Vite、Webpack)配置方式略有不同
- SCSS 语法需要编译为 CSS 才能在浏览器中运行
- 作用域样式需要配合 Vue 的
scoped属性使用 - 生产环境需要确保样式正确压缩和优化
三、基本用法
3.1 安装依赖
bash
# 使用 npm
npm install sass sass-loader -D
# 使用 yarn
yarn add sass sass-loader -D
# 使用 pnpm
pnpm add sass sass-loader -D
3.2 Vue 组件中使用 SCSS
html
<template>
<div class="container">
<h1 class="title">{{ title }}</h1>
</div>
</template>
<script setup>
import { ref } from 'vue'
const title = ref('Hello SCSS in Vue3')
</script>
<style lang="scss" scoped>
// 定义 SCSS 变量(编译后不再存在,仅在开发时使用)
$primary-color: #42b883;
$font-size: 16px;
.container {
padding: 20px;
.title {
color: $primary-color;
font-size: $font-size * 1.5;
// &: 引用父选择器,相当于 .container .title:hover
&:hover {
text-decoration: underline;
}
}
}
</style>
代码解析:
-
$primary-color / $font-size:SCSS 变量,编译时替换为实际值,不产生额外 CSS 规则。 -
&:hover :SCSS 嵌套语法中的父选择器引用,编译后为.container .title:hover。 -
scoped :Vue 提供的作用域样式,自动添加data-v-xxx属性,只作用于当前组件。
四、常用操作
4.1 全局样式文件引入
在 main.js 或 main.ts 中引入全局 SCSS 文件:
javascript
import { createApp } from 'vue'
import App from './App.vue'
import './styles/global.scss' // 引入全局样式,所有组件均可访问
createApp(App).mount('#app')
4.2 Vue 配置全局 SCSS 变量(Vite)
在 vite.config.js 中配置,使所有组件自动注入变量文件,无需手动 @import:
javascript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
css: {
preprocessorOptions: {
scss: {
// 自动在每个 SCSS 文件开头注入变量文件
additionalData: `@import "@/styles/variables.scss";`
}
}
}
})
常见坑:
additionalData 中的路径需确保与项目别名解析一致(如@ 对应src)。若使用sass 包(dart-sass),@import 可能在未来版本废弃,建议改用@use(参见官方文档)。
4.3 创建 SCSS 变量文件
src/styles/variables.scss:
scss
// 颜色变量
$primary-color: #42b883;
$secondary-color: #35495e;
$danger-color: #ff4757;
// 尺寸变量
$spacing-sm: 8px;
$spacing-md: 16px;
$spacing-lg: 24px;
// 响应式断点
$breakpoint-sm: 576px;
$breakpoint-md: 768px;
$breakpoint-lg: 992px;
五、高级用法
5.1 使用 Mixins
创建 src/styles/mixins.scss:
scss
@mixin flex-center($direction: row) {
display: flex;
justify-content: center;
align-items: center;
flex-direction: $direction;
}
@mixin responsive($breakpoint) {
@media (max-width: $breakpoint) {
@content;
}
}
在组件中使用:
scss
// 先引入 mixins
@import "@/styles/mixins";
.container {
@include flex-center(column);
@include responsive($breakpoint-md) {
padding: $spacing-sm;
}
}
代码解析:
-
@mixin:定义可复用的样式块,可带参数。 -
@include:将 mixin 插入当前位置。 -
@content:允许在 mixin 内部插入外部样式块,常用于媒体查询包装。
5.2 样式模块化
使用 Vue 的 module 属性实现 CSS Modules 风格:
js
<template>
<div :class="$style.container">
<h1 :class="$style.title">模块化样式</h1>
</div>
</template>
<style module lang="scss">
.container {
padding: 20px;
.title {
color: $primary-color;
}
}
</style>
划重点: $style 是 Vue 编译时生成的样式对象,类名会被哈希,避免全局冲突。
5.3 深度选择器
当需要覆盖子组件内部样式时,使用深度选择器:
scss
::v-deep(.child-component) {
color: red;
}
// 新版语法(推荐)
:deep(.child-component) {
color: red;
}
注意:
::v-deep 是 Vue 2 的写法,Vue 3 中支持但更推荐:deep()。两者语义相同,均会去掉scoped属性对当前选择器的限制。
六、项目结构建议
text
src/
├── styles/
│ ├── variables.scss # 全局变量
│ ├── mixins.scss # 混合器
│ ├── reset.scss # 重置样式
│ ├── global.scss # 全局样式
│ └── components/ # 组件样式(如按钮、弹窗等)
│ ├── button.scss
│ └── modal.scss
└── components/
└── MyComponent.vue
最后: 掌握 SCSS 集成后,配合 Vue 的单文件组件样式,可以大幅提高样式代码的复用性和可维护性。建议团队统一变量和 mixins 管理,形成样式规范,从项目初期就避免样式散乱的问题。