主题切换是一个常见的功能,以下实现这个功能
1. 下载依赖
# 安装依赖
npm install sass element-plus
2.创建一个hooks用来管理主题 src/shared/hooks/theme.ts
import { ref } from "vue";
type ThemeType = "light" | "dark" | "red" | "system";
// 主题配置
const themeConfig = {
light: {
// --el-color-primary 修改的是element-plus主题色
"--el-color-primary": "#409eff",
"--bg-color": "#ffffff",
"--text-color": "#303133",
},
dark: {
// --el-color-primary 修改的是element-plus主题色
"--el-color-primary": "#79bbff",
"--bg-color": "#141414",
"--text-color": "#e5eaf3",
},
red: {
// --el-color-primary 修改的是element-plus主题色
"--el-color-primary": "#fe6b00",
"--bg-color": "#fe6b00",
"--text-color": "#5a51f5",
},
};
// 状态管理
const theme = ref<ThemeType>(
(localStorage.getItem("theme") as ThemeType) || "light"
);
// 监听系统主题变化
const systemThemeMatch = window.matchMedia("(prefers-color-scheme: dark)");
// 获取当前生效主题
const getRealTheme = () => {
if (theme.value === "system") {
return systemThemeMatch.matches ? "dark" : "light";
}
return theme.value;
};
// 应用主题
const applyTheme = (themeType: "light" | "dark" | "red") => {
const variables = themeConfig[themeType];
Object.entries(variables).forEach(([key, value]) => {
document.documentElement.style.setProperty(key, value);
});
document.documentElement.className = themeType;
};
// 初始化监听
const initThemeListener = () => {
systemThemeMatch.addEventListener("change", () => {
if (theme.value === "system") {
applyTheme(getRealTheme());
}
});
};
// 切换主题
const toggleTheme = (newTheme: ThemeType) => {
theme.value = newTheme;
localStorage.setItem("theme", newTheme);
applyTheme(getRealTheme());
};
export function useTheme() {
return {
theme,
toggleTheme,
initThemeListener,
getRealTheme,
applyTheme,
};
}
3.main.ts 引入配置
import { createApp } from "vue";
import App from "./App.vue";
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
import { useTheme } from "./utils/theme";
const app: any = createApp(App);
// 初始化主题
const { initThemeListener, applyTheme, getRealTheme } = useTheme();
app.use(ElementPlus, {
theme: getRealTheme(),
});
applyTheme(getRealTheme());
initThemeListener();
app.mount("#app");
4.页面使用
<template>
<el-dropdown @command="handleCommand">
切换主题
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="light" :disabled="theme === 'light'">
亮色模式
</el-dropdown-item>
<el-dropdown-item command="dark" :disabled="theme === 'dark'">
暗黑模式
</el-dropdown-item>
<el-dropdown-item command="red" :disabled="theme === 'red'">
红色模式
</el-dropdown-item>
<el-dropdown-item command="system" :disabled="theme === 'system'">
跟随系统
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<div class="box">
我是主题字体颜色
</div>
<el-button>我是一个按钮</el-button>
</template>
<script setup lang="ts">
import { useTheme } from '../utils/theme.ts'
const { theme, toggleTheme } = useTheme()
const handleCommand = (command: string) => {
toggleTheme(command as ThemeType)
}
</script>
<style scoped lang="scss">
.box {
width: 100px;
height: 100px;
background-color: var(--bg-color);
color: var(--text-color);
}
</style>