前端(Vue框架)实现主题切换
来源:     阅读:3
易浩激活码
发布于 2025-11-07 15:33
查看主页

场景:

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>
 
 
// js
 
import useTheme from "@/utils/hooks/useTheme";
const { themeColors, setTheme} = useTheme()

3、定义主题颜色(theme.scss)

如果自定义的主题颜色与组件库样式终突,导致自定义的样式不生效,可在浏览器dom树中查引用的变量,直接修改变量样式即可,类似于下方的【--el-color-primary-light-9: #93c6fa; // 鼠标滑过.el-button背景色】



// 经典蓝色
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"; // 主题颜色

免责声明:本文为用户发表,不代表网站立场,仅供参考,不构成引导等用途。 系统环境
相关推荐
【粉丝投稿】工作2年经验成功上岸拿到字节offer,附上大佬的字节用户端一二三面面经(已OC)
数据可视化 | Grafana-初级篇
也许,你可以像我这样来了解KMP模式匹配算法
Python3.7源码在linux(ubuntu)下的编译和安装
程序员的迷茫:前台能做什么?还是后台?全栈?
首页
搜索
订单
购物车
我的