全局样式变量文件
src\assets\style\variables.scss
/*
CSS 自定义属性(--border-color)
- 定义位置:定义位置:通常放在一个全局样式文件中(例如 variables.scss),使用 :root 选择器定义,如 :root { --border-color: #ebeef5; }。
- 引入方式:该全局样式文件必须在应用入口(如 main.ts 或 App.vue)中引入一次,例如 import '@/assets/style/variables.scss',这样变量才会在整个应用生效。
- 使用方式:在任意组件的 <style> 中直接使用 var(--border-color),无需再导入该变量文件(因为已经全局引入过了)。
- 特点:运行时解析、可继承、支持动态修改,适合全局主题变量。
*/
:root {
// ========== 颜色变量 ==========
// 当前选中目标的背景色
--current-selected-color: #daeafb;
// 边框颜色
// --border-color: #ebeef5;
--border-color: #000;
// ========== 尺寸变量 ==========
// 短宽按钮,两个汉字,预留加载空间
--short-btn-width: 70px;
// 长宽按钮,四个汉字,预留加载空间
--long-btn-width: 107px;
// 表格行内短宽按钮,两个汉字,预留加载空间
--table-row-short-btn-width: 50px;
// 表格行内长宽按钮,四个汉字,预留加载空间
--table-row-long-btn-width: 80px;
// 对话框按钮
--dialog-btn-width: 100px;
// 阴影
--box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
// 内阴影(inset),模糊半径20px(无偏移)
--box-shadow-inset: inset 0 0 20px #d4def6;
}
/*
SCSS 变量($border-color)
- 定义位置:同样放在变量文件中,但无需 :root,直接 $border-color: #ebeef5;。
- 使用方式:如果通过构建工具(如 Vite 的 additionalData)全局注入,则组件中也无需手动导入;否则需要在每个组件的 <style lang="scss"> 中通过 @import 引入变量文件。
- 特点:编译时替换,不保留运行时变量。
- 缺点:如果多个组件都要使用,每个组件都要导入变量文件,稍微麻烦。
- 建议:如果坚持使用 SCSS 变量,推荐采用 Vite 的 additionalData 配置,实现全局注入,避免每个组件导入
*/
// ========== 颜色变量 ==========
// 边框颜色
$border-color: #000;
/*
【总结】两种方式都需要一次全局引入(CSS 变量是引入定义文件,SCSS 变量是引入变量文件或构建注入)。
关键区别在于:
- CSS 变量定义一次,运行时全局可用,组件使用时不需额外导入。
- SCSS 变量默认需要按需导入(除非配置全局注入),但编译后无运行时开销。
*/
应用示例
全局导入
src\main.ts
TypeScript
// 使用侧效应导入,使用别名 @(相当于./src)全局引入自定义样式变量
import "@/assets/style/variables.scss";
组件使用
src\components\layout\LayoutBasePage.vue
html
<script setup lang="ts">
/**
* 基础页面布局: 头部、主内容、底部
*/
defineOptions({
name: "LayoutBasePage"
});
</script>
<template>
<el-container class="container">
<el-header class="header">
<!-- 头部区域 -->
<slot name="header" />
</el-header>
<el-main class="main">
<!-- 主要区域 -->
<slot name="main" />
</el-main>
<el-footer class="footer">
<!-- 底部区域 -->
<slot name="footer" />
</el-footer>
</el-container>
</template>
<style scoped lang="scss">
// SCSS 变量,如果没有配置全局注入,每个组件都要手动导入
@import "@/assets/style/variables.scss";
// 选择 container 所有直接子元素(不包括孙级)
.container > * {
margin: 0;
padding: 0;
}
.container {
height: 100%;
border: 1px solid $border-color; // SCSS 变量($border-color)
.header {
height: auto;
}
.main {
border-top: 1px solid var(--border-color); // CSS 自定义属性(--border-color)
}
.footer {
height: auto;
padding: 0 10px;
}
}
</style>
详细讲解
CSS 自定义属性(--border-color)
-
定义位置 :通常放在一个全局样式文件中(例如
variables.scss),使用:root选择器定义,如:root { --border-color: #ebeef5; }。 -
引入方式 :该全局样式文件必须在应用入口(如
main.ts或App.vue)中引入一次,例如import '@/assets/style/variables.scss',这样变量才会在整个应用生效。 -
使用方式 :在任意组件的
<style>中直接使用var(--border-color),无需再导入该变量文件(因为已经全局引入过了)。 -
特点:运行时解析、可继承、支持动态修改,适合全局主题变量。
对比 SCSS 变量($border-color)
-
定义位置 :同样放在变量文件中,但无需
:root,直接$border-color: #ebeef5;。 -
使用方式 :如果通过构建工具(如 Vite 的
additionalData)全局注入,则组件中也无需手动导入;否则需要在每个组件的<style lang="scss">中通过@import引入变量文件。 -
特点:编译时替换,不保留运行时变量。
总结
两种方式都需要一次全局引入(CSS 变量是引入定义文件,SCSS 变量是引入变量文件或构建注入)。关键区别在于:
-
CSS 变量定义一次,运行时全局可用,组件使用时不需额外导入。
-
SCSS 变量默认需要按需导入(除非配置全局注入),但编译后无运行时开销。
方案一:使用 CSS 自定义属性(推荐)
1. 定义全局变量文件 src/assets/style/variables.scss
scss
// variables.scss
:root {
/* 边框颜色 */
--border-color: #ebeef5;
}
2. 在应用入口 main.ts 中全局引入
ts
// main.ts
import { createApp } from 'vue';
import App from './App.vue';
import '@/assets/style/variables.scss'; // 全局引入一次
createApp(App).mount('#app');
3. 在任意组件中使用
vue
<!-- LayoutBasePage.vue -->
<style scoped lang="scss">
.container {
border: 1px solid var(--border-color); /* 使用 CSS 变量 */
}
</style>
vue
<!-- AcceptQuery.vue -->
<style scoped lang="scss">
.aside {
border-right: 1px solid var(--border-color);
}
</style>
优点 :组件无需导入变量文件,因为变量已在全局 :root 中定义并随入口文件加载。
方案二:使用 SCSS 变量(需配置全局注入)
1. 定义 SCSS 变量文件 src/assets/style/variables.scss
scss
// variables.scss
$border-color: #ebeef5;
2. 配置构建工具全局注入(Vite 示例)
ts
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
css: {
preprocessorOptions: {
scss: {
// 全局注入,每个组件的 <style lang="scss"> 自动添加此导入
additionalData: `@import "@/assets/style/variables.scss";`
}
}
}
});
3. 组件中直接使用(无需手动导入)
vue
<!-- LayoutBasePage.vue -->
<style scoped lang="scss">
.container {
border: 1px solid $border-color; /* 直接使用 SCSS 变量 */
}
</style>
两个方案对比
| 方案 | 定义方式 | 组件使用 | 是否需要额外导入/配置 |
|---|---|---|---|
| CSS 变量 | :root { --border-color: #ebeef5; } |
var(--border-color) |
只需在入口 main.ts 导入一次 |
| SCSS 变量 | $border-color: #ebeef5; |
$border-color |
需通过构建工具全局注入,或每个组件手动 @import |
实际替换示例
假设你要统一替换 LayoutBasePage.vue 和 AcceptQuery.vue 中的边框颜色:
LayoutBasePage.vue(使用 CSS 变量)
scss
.container {
height: 100%;
border: 1px solid var(--border-color);
.main {
border-top: 1px solid var(--border-color);
}
}
AcceptQuery.vue(使用 CSS 变量)
scss
.layout-container {
height: 100%;
}
.aside {
width: 150px;
border-right: 1px solid var(--border-color);
}
.footer {
height: 42px;
padding: 5px;
border-top: 1px solid var(--border-color);
}
总结 :推荐使用 CSS 自定义属性,因为引入一次即可全局使用,无需关心组件导入问题,且未来换肤更灵活。如果团队更习惯 SCSS 变量,则建议配合 Vite 全局注入减少重复导入。
下面是使用 SCSS 变量但未配置全局注入 时的示例,即需要手动在每个组件的 <style lang="scss"> 中导入变量文件。
1. 定义 SCSS 变量文件
创建 src/assets/style/variables.scss:
scss
// variables.scss
$border-color: #ebeef5;
$border-width: 1px;
$border-style: solid;
2. 在组件中手动导入并使用
示例:LayoutBasePage.vue
vue
<style scoped lang="scss">
// 手动导入变量文件(路径根据项目调整)
@import "@/assets/style/variables.scss";
.container {
height: 100%;
border: $border-width $border-style $border-color; // 使用变量
.main {
border-top: $border-width $border-style $border-color;
}
}
</style>
示例:AcceptQuery.vue
vue
<style scoped lang="scss">
@import "@/assets/style/variables.scss"; // 每个组件都要写这一行
.aside {
width: 150px;
border-right: $border-width $border-style $border-color;
}
.footer {
border-top: $border-width $border-style $border-color;
}
</style>
示例:AcceptModify.vue
vue
<style scoped lang="scss">
@import "@/assets/style/variables.scss"; // 同样需要导入
.layout-container {
border: $border-width $border-style $border-color;
}
</style>
3. 缺点与解决方案
缺点:
- 每个使用 SCSS 变量的组件都必须手动
@import变量文件,当组件数量多时,重复导入显得繁琐,且容易遗漏。
解决方案:
-
使用构建工具(如 Vite 的
additionalData)全局注入变量文件,从而避免在每个组件中重复导入。 -
或改用 CSS 自定义属性(
--border-color),在入口文件全局引入一次,组件中直接使用var(),无需导入。
总结
未配置全局注入时,SCSS 变量需要手动导入,虽然可行但不够便捷。如果项目开始时就计划大量使用 SCSS 变量,建议尽早配置全局注入,以提升开发体验。