vue3 主题模式 结合 element-plus的主题

news2025/4/22 7:30:40

vue3 主题模式 结合 element-plus的主题

 npm i element-plus --save-dev

在 Vue 3 中,实现主题模式主要有以下几种方式

1.使用 CSS 变量(自定义属性)
  • CSS 变量是一种在 CSS 中定义可重用值的方式。在主题模式中,可以将颜色、字体大小等样式属性设置为 CSS 变量。然后通过 JavaScript 或 Vue 的响应式特性来切换这些变量的值,从而实现主题的切换
var.css
:root {
    --login-bg-color: #293146;  
    --left-menu-max-width: 200px;
    --left-menu-min-width: 64px;
    --left-menu-bg-color: #001529;
    --left-menu-bg-light-color: #0f2438;
    --left-menu-bg-active-color: var(--el-color-primary);
    --left-menu-text-color: #bfcbd9;
    --left-menu-text-active-color: #fff;
    --left-menu-collapse-bg-active-color: var(--el-color-primary);
    --logo-height: 50px;
    --logo-title-text-color: #fff;
    --top-header-bg-color: '#fff';
    --top-header-text-color: 'inherit';
    --top-header-hover-color: #f6f6f6;
    --top-tool-height: var(--logo-height);  
    --top-tool-p-x: 0;
    --tags-view-height: 35px;
    --tab-menu-max-width: 80px;
    --tab-menu-min-width: 30px;
    --tab-menu-collapse-height: 36px;   
  }
  .dark {
    --app-content-bg-color: var(--el-bg-color);
  }
  html,
  body {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }
  
  *,
  :after,
  :before {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
  
index.scss
@use './var.css';
@use 'element-plus/theme-chalk/dark/css-vars.css';

2.在main 引入 index.scss
// 引入全局样式
import '@/styles/index.scss'

3.在 Vue 组件中动态切换主题
<script setup lang="ts">
import { useAppStore } from '@/store/modules/app' //引入的状态管理
import { ThemeSwitch } from '@/components/ThemeSwitch' // 引入的组件黑白切换

const appStore =  useAppStore()
const textColor = computed(() => appStore.getTextColor)
appStore.initTheme() // Pinia 实现状态管理 

</script>

<template>
  <!--element-plus ElConfigProvider 组件的的封装-->
  <ConfigGlobal>
    <!-- <p style="color: var(--el-text-color-primary);">p标签</p> -->
    <p :style="{'color':textColor}"  >p标签</p>
    <ThemeSwitch></ThemeSwitch>
  </ConfigGlobal>
  
</template>

<style scoped lang="scss">
$prefix-cls: #{$namespace}-app;

.size {
  width: 100%;
  height: 100%;
}

html,
body {
  @extend .size;

  padding: 0 !important;
  margin: 0;
  overflow: hidden;

  #app {
    @extend .size;
  }
}

.#{$prefix-cls}-grey-mode {
  filter: grayscale(100%);
}

</style>

注意:CSS 变量与样式冲突解决

  • 如果你自定义的主题与 Element Plus 的默认样式冲突,可以通过在你的主题 CSS 文件中明确覆盖 Element Plus 的变量来解决。
  • 在 var.css 中,确保所有需要覆盖的变量都被正确设置
  • element-plus 在vite.config.ts 配置自动导入

store/modules/app.ts

import { defineStore } from "pinia";
// import { store } from '../index'
// import { colorIsDark, hexToRGB, lighten, mix } from '@/utils/color'
import { setCssVar,humpToUnderline } from '@/utils'
import { useDark } from '@vueuse/core'  安装 @vueuse/core

export const useAppStore  = defineStore('app', {
   state: () => {
      return {
         isCollapse: false, // 菜单是否折叠
         isFullScreen: false, // 页面是否全屏
         isDark:false, // 是否是暗黑模式
         textColor: '#303133',
         theme:{
            //文字的颜色
            // 主题色
            elColorPrimary: '#409eff',
            // 左侧菜单边框颜色
            leftMenuBorderColor: 'inherit',
            // 左侧菜单背景颜色
            leftMenuBgColor: '#001529',
            // 左侧菜单浅色背景颜色
            leftMenuBgLightColor: '#0f2438',
            // 左侧菜单选中背景颜色
            leftMenuBgActiveColor: 'var(--el-color-primary)',
            // 左侧菜单收起选中背景颜色
            leftMenuCollapseBgActiveColor: 'var(--el-color-primary)',
            // 左侧菜单字体颜色
            leftMenuTextColor: '#bfcbd9',
            // 左侧菜单选中字体颜色
            leftMenuTextActiveColor: '#fff',
            // logo字体颜色
            logoTitleTextColor: '#fff',
            // logo边框颜色
            logoBorderColor: 'inherit',
            // 头部背景颜色
            topHeaderBgColor: '#fff',
            // 头部字体颜色
            topHeaderTextColor: 'inherit',
            // 头部悬停颜色
            topHeaderHoverColor: '#f6f6f6',
            // 头部边框颜色
            topToolBorderColor: '#eee'
          }
      } 
   },
   getters:{
    getIsDark(): boolean {
        return this.isDark
      },
    getTextColor(): string {
        return this.textColor
      }
   },
   actions: {
    setIsDark(isDark: boolean) {
        this.isDark = isDark
        if (this.isDark) {
        //  setCssVar('--el-text-color-primary', 'red')
          document.documentElement.classList.add('dark')
          document.documentElement.classList.remove('light')
        } else {
        //   setCssVar('--el-text-color-primary', '#303133')
          document.documentElement.classList.add('light')
          document.documentElement.classList.remove('dark')
        }
        this.textColor = this.isDark? 'red' : '#303133'
        // wsCache.set(CACHE_KEY.IS_DARK, this.isDark)
      },  
      setCssVarTheme() {
        for (const key in this.theme) {
          setCssVar(`--${humpToUnderline(key)}`, this.theme[key])
        }
       // this.setPrimaryLight()
      },
      setPrimaryLight() {
        if (this.theme.elColorPrimary) {
          const elColorPrimary = this.theme.elColorPrimary
          const color = this.isDark ? '#000000' : '#ffffff'
          const lightList = [3, 5, 7, 8, 9]
          lightList.forEach((v) => {
            setCssVar(`--el-color-primary-light-${v}`, mix(color, elColorPrimary, v / 10))
          })
          setCssVar(`--el-color-primary-dark-2`, mix(color, elColorPrimary, 0.2))
        }
      },
      initTheme() {
        const isDark = useDark({
          valueDark: 'dark',
          valueLight: 'light'
        })
        isDark.value = this.getIsDark
       
      },
   },
 
  
   persist: true
})


// export const useAppStoreWithOut = () => {
//    return useAppStore(store)
//  }
// 使用到的函数
export const setCssVar = (prop: string, val: any, dom = document.documentElement) => {
  dom.style.setProperty(prop, val)
}

/**
 * @param str 需要转下划线的驼峰字符串
 * @returns 字符串下划线
 */
export const humpToUnderline = (str: string): string => {
  return str.replace(/([A-Z])/g, '-$1').toLowerCase()
}

themeSwitch.vue

<script lang="ts" setup>
import { useAppStore } from '@/store/modules/app'
import { useIcon } from '@/hooks/web/useIcon'
import { useDesign } from '@/hooks/web/useDesign'
defineOptions({ name: 'ThemeSwitch' })

const { getPrefixCls } = useDesign()

// const prefixCls = getPrefixCls('theme-switch')
const prePrefixCls = 'ad-theme-switch'
const Sun = useIcon({ icon: 'emojione-monotone:sun', color: '#fde047' })

const CrescentMoon = useIcon({ icon: 'emojione-monotone:crescent-moon', color: '#fde047' })

const appStore = useAppStore()

// 初始化获取是否是暗黑主题
// const isDark = ref(appStore.getIsDark)

// 设置switch的背景颜色
const blackColor = 'var(--el-color-black)'

// const themeChange = (val: boolean) => {
//   appStore.setIsDark(val)
// }
const isDark = computed({
  get() {
    return appStore.getIsDark
  },
  set(val: boolean) {
    appStore.setIsDark(val)

  }
})
</script>

<template>
  <el-switch
    v-model="isDark"
    :active-color="blackColor"
    :active-icon="Sun"
    :border-color="blackColor"
    :class="prefixCls"
    :inactive-color="blackColor"
    :inactive-icon="CrescentMoon"
    inline-prompt
  />
</template>
<style lang="scss" scoped>
:deep(.el-switch__core .el-switch__inner .is-icon) {
  overflow: visible;
}
</style>

初始化的主题 ConfigGlobal.vue

<script setup lang="ts">
import { ElConfigProvider } from 'element-plus'
import { useAppStore } from '@/store/modules/app'
import { useDesign } from '@/hooks/web/useDesign'

const { variables } = useDesign() // 命名规则

const appStore = useAppStore()

// 初始化所有主题色
onMounted(() => {
  appStore.setCssVarTheme()
})

</script>

<template>
  <ElConfigProvider
    :namespace="variables.elNamespace"
    :message="{ max: 1 }"
  >
    <slot></slot>
  </ElConfigProvider>
</template>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2339938.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[c语言日寄]免费文档生成器——Doxygen在c语言程序中的使用

【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋&#xff1a;这是一个专注于C语言刷题的专栏&#xff0c;精选题目&#xff0c;搭配详细题解、拓展算法。从基础语法到复杂算法&#xff0c;题目涉及的知识点全面覆盖&#xff0c;助力你系统提升。无论你是初学者&#xff0c;还是…

QtCreator的设计器、预览功能能看到程序图标,编译运行后图标消失

重新更换虚拟机&#xff08;Vmware Kylin&#xff09;&#xff0c;重新编译和配置了很多第三方库后&#xff0c;将代码跑到新的这个虚拟机环境中&#xff0c;但是出现程序图标不可见&#xff0c;占位也消失&#xff0c;后来继续检查ui文件&#xff0c;ui文件图标也异常&#x…

面试常用基础算法

目录 快速排序归并排序堆排序 n n n皇后问题最大和子数组爬楼梯中心扩展法求最长回文子序列分割回文串动态规划求最长回文子序列最长回文子串单调栈双指针算法修改 分割回文串滑动窗口栈 快速排序 #include <iostream> #include <algorithm>using namespace std;…

悬空引用和之道、之禅-《分析模式》漫谈57

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 “Analysis Patterns”的第5章“对象引用”原文&#xff1a; Unless you can catch all such references, there is the risk of a dangling reference, which often has painful con…

【初阶数据结构】树——二叉树(上)

文章目录 目录 前言 一、树 1.树的概念与结构 2.树相关术语 3.树的表示 二、二叉树 1.概念与结构 2.特殊的二叉树 3.二叉树存储结构 总结 前言 本篇带大家学习一种非线性数据结构——树&#xff0c;简单认识树和二叉数以及了解二叉树的存储结构。 一、树 1.树的概念与结构 树…

ECharts散点图-散点图14,附视频讲解与代码下载

引言&#xff1a; ECharts散点图是一种常见的数据可视化图表类型&#xff0c;它通过在二维坐标系或其它坐标系中绘制散乱的点来展示数据之间的关系。本文将详细介绍如何使用ECharts库实现一个散点图&#xff0c;包括图表效果预览、视频讲解及代码下载&#xff0c;让你轻松掌握…

GAIA-2:用于自动驾驶的可控多视图生成世界模型

25年3月来自英国创业公司 Wayze 的论文“GAIA-2: A Controllable Multi-View Generative World Model for Autonomous Driving”。&#xff08;注&#xff1a;23年9月其发布GAIA-1&#xff09; 生成模型为模拟复杂环境提供一种可扩展且灵活的范例&#xff0c;但目前的方法不足…

浅谈AI致幻

文章目录 当前形势下存在的AI幻觉&#xff08;AI致幻&#xff09;什么是AI幻觉AI幻觉的类型为什么AI会产生幻觉AI幻觉的危害与影响当前应对AI幻觉的技术与方法行业与学术界的最新进展未来挑战与展望结论 当前形势下存在的AI幻觉&#xff08;AI致幻&#xff09; 什么是AI幻觉 …

车载软件架构 --- 二级boot设计说明需求规范

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁,漫无目的走着,大概这就是成年人最深的孤独吧! 旧人不知我近况,新人不知我过…

Java高效合并Excel报表实战:GcExcel让数据处理更简单

前言&#xff1a;为什么需要自动化合并Excel&#xff1f; 在日常办公场景中&#xff0c;Excel报表合并是数据分析的基础操作。根据2023年企业办公效率报告显示&#xff1a; 财务人员平均每周花费6.2小时在Excel合并操作上人工合并的错误率高达15%90%的中大型企业已采用自动化…

第十四届蓝桥杯 2023 C/C++组 平方差

目录 题目&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; 思路&#xff1a; 核心思路&#xff1a; 第一种思路&#xff1a; 第二种思路&#xff1a; 坑点&#xff1a; 代码&#xff1a; 数学找规律 O(n) 50分代码详解&#xff1a; O(1)满分代码详解&#x…

I/O复用函数的使用——select

I/O复用函数的使用——select 目录 一、概念 二、select接口 2.1 基础概念 2.2 使用 select 函数的标准输入读取代码 2.3 基于 select 模型的多客户端 TCP 服务器实现 一、概念 i/o复用使得程序能同时监听多个文件描述符&#xff0c;可以提高程序性能。 之前为了让服务器能…

图像预处理-图像轮廓特征查找

其实就是外接轮廓&#xff0c;有了轮廓点就可以找到最上、最下、最左、最右的四个坐标&#xff08;因为有xmin,xmax,ymin,ymax&#xff09;。就可以绘制出矩形。 一.外接矩形 cv.boundingRect(轮廓点) - 返回x,y,w,h&#xff0c;传入一个轮廓的轮廓点&#xff0c;若有多个轮廓需…

全同态加密医疗数据分析集python实现

目录 摘要一、前言二、全同态加密与医疗数据分析概述2.1 全同态加密(FHE)简介2.2 医疗数据分析需求三、数据生成与预处理四、系统架构与流程4.1 系统架构图五、核心数学公式六、异步任务调度与(可选)GPU 加速七、PyQt6 GUI 设计八、完整代码实现九、自查测试与总结十、展望…

list的学习

list的介绍 list文档的介绍 list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。list的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向其前一个元素和后一…

HarmonyOS:Navigation实现导航之页面设置和路由操作

导读 设置标题栏模式设置菜单栏设置工具栏路由操作页面跳转页面返回页面替换页面删除移动页面参数获取路由拦截 子页面页面显示类型页面生命周期页面监听和查询 页面转场关闭转场自定义转场共享元素转场 跨包动态路由系统路由表自定义路由表 示例代码 Navigation组件适用于模块…

管道位移自动化监测方案

一、背景 管道系统在区域性地质沉降作用下易形成非均匀应力场集中现象&#xff0c;诱发管体屈曲变形及环焊缝界面剥离等连续损伤累积效应&#xff0c;进而导致管道力学性能退化与临界承载能力衰减。传统人工巡检受限于空间覆盖度不足及数据采集周期长&#xff08;≥72h&#xf…

【学习笔记】机器学习(Machine Learning) | 第五周| 分类与逻辑回归

机器学习&#xff08;Machine Learning&#xff09; 简要声明 基于吴恩达教授(Andrew Ng)课程视频 BiliBili课程资源 文章目录 机器学习&#xff08;Machine Learning&#xff09;简要声明 一、逻辑回归的基本原理分类判断条件模型输出的解释Sigmoid 函数与 Logistic 函数逻辑…

Python 深度学习 第8章 计算机视觉中的深度学习 - 卷积神经网络使用实例

Python 深度学习 第8章 计算机视觉中的深度学习 - 卷积神经网络使用实例 内容概要 第8章深入探讨了计算机视觉中的深度学习&#xff0c;特别是卷积神经网络&#xff08;convnets&#xff09;的应用。本章详细介绍了卷积层和池化层的工作原理、数据增强技术、预训练模型的特征…

[免费]SpringBoot+Vue博物馆(预约)管理系统【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue博物馆(预约)管理系统&#xff0c;分享下哈。 项目视频演示 【免费】SpringBootVue博物馆(预约)管理系统 Java毕业设计_哔哩哔哩_bilibili 项目介绍 随着计算机科学技术的日渐成熟&#xff…