以下是一个基于Vue3 + Sass的完整主题色解决方案,包含动态切换、状态管理、样式组织等核心模块:
一、项目结构设计
src/
├── styles/
│ ├── _variables.scss # 色板定义
│ ├── _mixins.scss # 主题混合
│ ├── theme.scss # 主题入口
│ └── components/ # 组件级样式
├── stores/
│ └── theme.js # Pinia主题状态管理
└── App.vue # 主题注入点
styles/_variables.scss
该文件定义可扩展的色板系统,支持后续新增主题
// 基础色板
$color-primary: #1890ff;
$color-success: #52c41a;
$color-warning: #faad14;
// 主题映射表
$themes: (
light: (
bg-color: #ffffff,
text-color: rgba(0, 0, 0, 0.85),
border-color: #d9d9d9
),
dark: (
bg-color: #141414,
text-color: rgba(255, 255, 255, 0.85),
border-color: #434343
)
);
styles/_mixins.scss
通过Sass混合器实现样式与主题的自动关联
mixin theme-property($property, $key) {
@each $theme-name, $theme-map in $themes {
[data-theme="#{$theme-name}"] & {
#{$property}: map-get($theme-map, $key);
}
}
}
@mixin theme-bg {
@include theme-property('background-color', 'bg-color');
}
@mixin theme-text {
@include theme-property('color', 'text-color');
}
stores/theme.js
集中管理主题状态并同步到DOM属性
{ defineStore } from 'pinia';
export const useThemeStore = defineStore('theme', {
state: () => ({
currentTheme: 'light'
}),
actions: {
toggleTheme() {
this.currentTheme = this.currentTheme === 'light' ? 'dark' : 'light';
document.documentElement.setAttribute('data-theme', this.currentTheme);
}
}
});
App.vue
<setup>
import { useThemeStore } from '@/stores/theme';
const themeStore = useThemeStore();
</script>
<template>
<div class="app-container">
<button @click="themeStore.toggleTheme">切换主题</button>
<!-- 其他内容 -->
</div>
</template>
<style lang="scss">
@import '@/styles/theme';
.app-container {
@include theme-bg;
transition: background-color 0.3s;
}
</style>
三、组件级应用示例
<template>
<div class="card">
<h3 class="title">主题演示卡片</h3>
<p class="content">当前主题: {{ themeStore.currentTheme }}</p>
</div>
</template>
<script setup>
import { useThemeStore } from '@/stores/theme';
const themeStore = useThemeStore();
</script>
<style lang="scss" scoped>
.card {
padding: 16px;
@include theme-bg;
border: 1px solid;
@include theme-property('border-color', 'border-color');
.title {
@include theme-text;
margin-bottom: 8px;
}
}
</style>
四、要点解析
-
动态切换原理
- 通过修改
data-theme属性触发CSS选择器匹配 - Sass编译时生成多套主题样式规则
- 通过修改
-
性能优化
-
使用CSS Variables作为降级方案:
:root { --primary: #{$color-primary}; --text-color: #{map-get(map-get($themes, 'light'), 'text-color')}; }
-