前端(Vue框架)实现主题切换
场景:
web项目或其他项目中难免有切换主题的需求,现在写一个较统一的方法
实现:
本篇文章记录的是:定义好需要的样式,切换主题时将其设置为 html 的自定义属性,从而达到样式替换的效果
还有一种方案:将不同的样式文件使用<link>标签关联到根文件的 html 文件头部,切换主题时,设置 link 标签 的 href 属性即可
1、hook函数:hooks/useTheme
import {watchEffect, ref} from 'vue'const LOCAL_KEY = "__theme__"export default function useTheme() {// 1. 主题列表(支持的主题及对应颜色)const themeColors = ref([{color: '#409eff', themeKey: 'classicBlue', themeName: "经典蓝色"},{color: '#312e6c', themeKey: 'deepPurple', themeName: "深邃紫"},]);const DEFAULT_THEME = themeColors.value[0].themeKey; // 默认主题const storedTheme = localStorage.getItem(LOCAL_KEY);const theme = ref(storedTheme ? JSON.parse(storedTheme).themeKey : DEFAULT_THEME);// 3. 监听主题变化:同步到DOM和本地存储watchEffect(() => {// 设置html的data-theme属性(用于CSS选择器)document.documentElement.dataset.theme = theme.value;// 保存到本地存储(持久化)let find = themeColors.value.find(it => it.themeKey === theme.value);localStorage.setItem(LOCAL_KEY, JSON.stringify(find));});// 主题切换方法(对外暴露)const setTheme = (newTheme) => {// 验证新主题是否在支持的列表中(可选,增强健壮性)const isValid = themeColors.value.some(item => item.themeKey === newTheme) || newTheme === 'light';if (isValid) {theme.value = newTheme;}};// 获取当前主题function getTheme() {return theme.value;}// 获取主题对应的背景色function getThemeColorStyle(color) {return {background: color};}// 获取存储键function getLocalKey() {return LOCAL_KEY;}// 获取默认的主题function getDefaultTheme() {return DEFAULT_THEME;}return {theme,getTheme,setTheme,getLocalKey,getThemeColorStyle,themeColors,getDefaultTheme}
}2、组件使用处:
<el-dropdown-item command="theme" class="skin-dropitem">{{ $t('homePage.switchTheme') }}<!--    主题列表--><div class="skin-btns"><div class="themeColors_box"><div v-for="(item, index) in themeColors" :key="index"@click="setTheme(item.themeKey)">{{item.themeName}}</div></div></div></el-dropdown-item>// jsimport useTheme from "@/utils/hooks/useTheme";
const { themeColors, setTheme} = useTheme()
3、定义主题颜色(theme.scss)
// 经典蓝色
html[data-theme="classicBlue"] {--currentMessage-bg-color: #409eff; // 消息页面分类按钮背景--sidebar-bg-color: #409eff; // 主页面导肮栏背景--sidebar-is-active-bg-color: #245a8d; // 主页面导肮栏激活的背景--sidebar-hover-bg-color: #3278bf; // 主页面导肮栏鼠标滑过的背景--el-button--primary: #409eff; // element-plus 样式--el-color-primary-light-9: #93c6fa; // 鼠标滑过.el-button背景色
}// 深邃紫
html[data-theme="deepPurple"] {--currentMessage-bg-color: #312e6c;--sidebar-bg-color: #312e6c;--sidebar-hover-bg-color: #4a449d;--sidebar-is-active-bg-color: #181837;--el-button--primary: #312e6c;--el-color-primary-light-9: #938fff;
}4、将主题颜色引入到入口文件(main.ts)进行挂载
import "../../styles/theme.scss"; // 主题颜色