前端(Vue框架)实现主题切换

  • 时间:2025-11-07 15:33 作者: 来源: 阅读:0
  • 扫一扫,手机访问
摘要:场景: web项目或其他项目中难免有切换主题的需求,现在写一个较统一的方法 实现: 本篇文章记录的是:定义好需要的样式,切换主题时将其设置为 html 的自定义属性,从而达到样式替换的效果 还有一种方案:将不同的样式文件使用<link>标签关联到根文件的 html 文件头部,切换主题时,设置 link 标签 的 href 属性即可 1、hook函数:hooks/u

场景:

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

  • 全部评论(0)
最新发布的资讯信息
【系统环境|】看技术文档和手顺方法(2025-11-07 15:34)
【系统环境|】前端(Vue框架)实现主题切换(2025-11-07 15:33)
【系统环境|】c# OpenCV 基于成像色度计的汽车氛围灯亮度色度计算(2025-11-07 15:33)
【系统环境|】JAVA 接口文档优化 —— 用 Knife4j 让前后端对接 “零沟通”(参数、权限、示例全说清)(2025-11-07 15:32)
【系统环境|】BPF for HID drivers(2025-11-07 15:32)
【系统环境|】202506 CCF-GESP编程能力等级认证Scratch一级真题 建议答题时长:60min(2025-11-07 15:31)
【系统环境|】动态调整身份验证安全级别(2025-11-07 15:31)
【系统环境|】【AI辅助生成】QT 3D基础设施技术架构分析 为什么QT 3D技术栈如此复杂?(2025-11-07 15:30)
【系统环境|】HTML 事件(2025-11-07 15:30)
【系统环境|】JavaScript 性能优化实战:从 “卡顿列表” 到 “丝滑交互”,我踩过的坑和总结的招(2025-11-07 15:29)
手机二维码手机访问领取大礼包
返回顶部