Vue3 集成 SCSS 配置

在 Vue3 项目中希望使用 SCSS 来提升样式代码的可维护性和开发效率,但配置方式与高级用法容易混淆。这篇就来聊清楚 Vue3 集成 SCSS 的完整流程、常见场景和进阶技巧。

  1. 安装与基础配置:不同构建工具下的依赖安装与配置步骤
  2. 全局变量与混合器:如何共享变量与 mixin,避免重复定义
  3. 高级用法:样式模块化、深度选择器、响应式 mixin

一、使用场景

  • 需要使用 CSS 变量和主题切换功能
  • 大型项目中的样式模块化管理
  • 需要复用样式代码(mixins、继承)
  • 复杂的样式逻辑处理

二、注意事项

  1. 需要安装相应的 SCSS 编译器依赖(sass + sass-loader
  2. 不同构建工具(Vite、Webpack)配置方式略有不同
  3. SCSS 语法需要编译为 CSS 才能在浏览器中运行
  4. 作用域样式需要配合 Vue 的 scoped 属性使用
  5. 生产环境需要确保样式正确压缩和优化

三、基本用法

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>

代码解析:

  1. $primary-color / $font-size:SCSS 变量,编译时替换为实际值,不产生额外 CSS 规则。
  2. &:hover :SCSS 嵌套语法中的父选择器引用,编译后为 .container .title:hover
  3. 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;
  }
}

代码解析:

  1. @mixin:定义可复用的样式块,可带参数。
  2. @include:将 mixin 插入当前位置。
  3. @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 管理,形成样式规范,从项目初期就避免样式散乱的问题。