当前位置: 首页 > news >正文

vue3+element-plus项目主题色切换;element-plus换肤

文章目录

  • 前言
  • 一、实现方案
    • 1.使用css变量+class
    • 2. 切换主题
    • 3. 实现思路
    • 4.对比其他方案
  • 二、具体实现
    • 1. 默认主题色
    • 2. 定义一套或多套定制主题色
      • 2.1新增src/style/theme.scss
      • 2.2main.js引入
    • 3. 构建配置
    • 4. 切换逻辑和持久化
      • 4.1 动态添加class
      • 4.2 持久化
    • 5. 组件引入
    • 6. main.js初始化主题色
  • 二、 涉及变更
    • 1. element-plus、vxe-table、antv/g6、echarts等第三方组件库
    • 2. 原生html
    • 3. 背景图
  • 三、其他换色思路
    • 1.主题方式
    • 2.别的博主实现方式


前言

提示:该方案足以实现切换主题色功能,具体截图待补充

场景:当前vue3+element-plus的项目,要求实现点击按钮切换主题色
注意项:切换主题色,不仅涉及到element-plus的组件样式,还需要手动变更原生的html等div样式;如果涉及第三方组件库(例如:vxe-table、echarts)同样需要修改样式

暂时截图
在这里插入图片描述

一、实现方案

1.使用css变量+class

css变量使用说明

原因:

  • element-plus和vxe-table等组件库,内部样式均是通过使用通用的css变量(例如–el-color-primary、–el-color-primary-light-5等),通过修改对应css变量即可修改组件样式
  • 通过自定义通用css变量,多页面共用,统一维护;

2. 切换主题

参考element-plus组件库切换主题色逻辑:

  • 动态给html标签添加class类名,针对不同类名修改css变量值和定制化样式,以此实现系统换肤

在这里插入图片描述

3. 实现思路

  • 定义多个主题(默认、暗黑、自定义品牌色)
  • 修改与 绑定全局 CSS 变量
  • 切换时修改 HTML 或 body 的 class
  • 主题切换状态持久化(localStorage)
  • 页面组件响应式刷新主题色(通过变量)

4.对比其他方案

当前方案:使用css变量+class

其他:
1.使用主题SCSS 多套主题构建:
优点:风格完全隔离,稳定性强
缺点:基于element-plus封装的公司组件库,项目也引入使用了,但是这种方式就无法渗透改变公司组件库样式(而上述css变量+class却可以实现全局所有样式的修改)

二、具体实现

首先需要配置一套默认的主题色,可直接参考链接:配置默认主题色

1. 默认主题色

src/style/element.scss

// index.scss
@forward "element-plus/theme-chalk/src/common/var.scss" with ($colors: ("white": #ffffff,"black": #000000,"primary": ("base": #007d7b),"success": ("base": #8bc34a),"warning": ("base": #ffc107),"danger": ("base": #f56c6c),"error": ("base": #ff5722),"info": ("base": #909399))
);

2. 定义一套或多套定制主题色

2.1新增src/style/theme.scss

至于如何找到element-plus的css变量,可以直接看控制台的:root变量

/** element内置暗黑主题 */
@use "element-plus/theme-chalk/src/dark/css-vars.scss" as *;// 可以进行一些样式的覆盖
html {--v-bg-color: #1fff; // 新增公共变量 -其他页面可用使用 color: var(--v-bg-color)
}html.skins {--my-css-wbg: #223648;// Element Plus 主色--el-color-primary: #0084cb;--el-color-success: #2bc667;--el-color-warning: #f4c42d;--el-color-danger: #f56c6c;--el-color-error: #ff5722;--el-color-info: #909399;color-scheme: dark;--el-color-white: #ffffff;--el-color-black: #333;--el-color-primary-light-3: #4da9db;--el-color-primary-light-5: #80c2e5;--el-color-primary-light-7: #b3daef;--el-color-primary-light-8: #cce6f5;--el-color-primary-light-9: #e6f3fa;--el-color-primary-dark-2: #006aa2;--el-color-success-light-3: #6bd795;--el-color-success-light-5: #95e3b3;--el-color-success-light-7: #bfeed1;--el-color-success-light-8: #d5f4e1;--el-color-success-light-9: #eaf9f0;--el-color-success-dark-2: #229e52;--el-color-warning-light-3: #f7d66c;--el-color-warning-light-5: #fae296;--el-color-warning-light-7: #fcedc0;--el-color-warning-light-8: #fdf3d5;--el-color-warning-light-9: #fef9ea;--el-color-warning-dark-2: #c39d24;--el-color-danger-light-3: #f89898;--el-color-danger-light-5: #fab6b6;--el-color-danger-light-7: #fcd3d3;--el-color-danger-light-8: #fde2e2;--el-color-danger-light-9: #fef0f0;--el-color-danger-dark-2: #c45656;--el-color-error-light-3: #ff8964;--el-color-error-light-5: #ffab91;--el-color-error-light-7: #ffcdbd;--el-color-error-light-8: #ffddd3;--el-color-error-light-9: #ffeee9;--el-color-error-dark-2: #cc461b;--el-color-info-light-3: #b1b3b8;--el-color-info-light-5: #c8c9cc;--el-color-info-light-7: #dedfe0;--el-color-info-light-8: #e9e9eb;--el-color-info-light-9: #f4f4f5;--el-color-info-dark-2: #7d8085;--el-bg-color: #f1ff;--el-bg-color-page: #f2f3f5;--el-bg-color-overlay: #ffffff;--el-text-color-primary: #303133;--el-text-color-regular: #606266;--el-text-color-secondary: #909399;--el-text-color-placeholder: #a8abb2;--el-text-color-disabled: #c0c4cc;--el-border-color: #dcdfe6;--el-border-color-light: #e4e7ed;--el-border-color-lighter: #ebeef5;--el-border-color-extra-light: #f2f6fc;--el-border-color-dark: #d4d7de;--el-border-color-darker: #cdd0d6;--el-fill-color: #f0f2f5;--el-fill-color-light: #f5f7fa;--el-fill-color-lighter: #fafafa;--el-fill-color-extra-light: #fafcff;--el-fill-color-dark: #ebedf0;--el-fill-color-darker: #e6e8eb;--el-fill-color-blank: #ffffff;--el-box-shadow: 0px 12px 32px 4px rgba(0, 0, 0, 0.04), 0px 8px 20px rgba(0, 0, 0, 0.08);--el-box-shadow-light: 0px 0px 12px rgba(0, 0, 0, 0.12);--el-box-shadow-lighter: 0px 0px 6px rgba(0, 0, 0, 0.12);--el-box-shadow-dark: 0px 16px 48px 16px rgba(0, 0, 0, 0.08), 0px 12px 32px rgba(0, 0, 0, 0.12), 0px 8px 16px -8px rgba(0, 0, 0, 0.16);--el-disabled-bg-color: var(--el-fill-color-light);--el-disabled-text-color: var(--el-text-color-placeholder);--el-disabled-border-color: var(--el-border-color-light);--el-overlay-color: rgba(0, 0, 0, 0.8);--el-overlay-color-light: rgba(0, 0, 0, 0.7);--el-overlay-color-lighter: rgba(0, 0, 0, 0.5);--el-mask-color: rgba(255, 255, 255, 0.9);--el-mask-color-extra-light: rgba(255, 255, 255, 0.3);--el-border-width: 1px;--el-border-style: solid;--el-border-color-hover: var(--el-text-color-disabled);--el-border: var(--el-border-width) var(--el-border-style) var(--el-border-color);--el-svg-monochrome-grey: var(--el-border-color);--el-input-bg-color: var(--my-css-wbg);--el-fill-color-blank: var(--my-css-wbg);--vxe-primary-color: #0084cb;--vxe-ui-layout-background-color: #223648;--vxe-ui-table-header-background-color: #20496e; // 表格头背景--vxe-ui-table-row-striped-background-color: #243c52;--vxe-ui-font-color: #ffffff; // 表格字体颜// vxe-table.vxe-toolbar-custom-target {background-color: var(--vxe-primary-color)!important;}.wbg {background-color: var(--my-css-wbg);}.theme_div {background-color: #1fff;}
}

2.2main.js引入

@use "element-plus/theme-chalk/src/index.scss";
@import "./theme.scss";

3. 构建配置

vite.config.js

 { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'export default defineConfig({css: {preprocessorOptions: {scss: {additionalData: `@use "@/style/element.scss" as *; `}}}
})

4. 切换逻辑和持久化

新增src/utils/theme.js

export const currentTheme = ref((localStorage.getItem('app_theme')) || 'light'
)
export function toggleTheme() {currentTheme.value = currentTheme.value === 'light' ? 'dark' : 'light'localStorage.setItem('app_theme', currentTheme.value)//页面挂载时,根据数据库的用户皮肤主题,渲染页面的主题applyTheme2(currentTheme.value)
}
export function applyTheme(theme) {if (theme === 'light') {//此时为默认状态,移除html的skins样式document.documentElement.classList.remove('skins'); //该段代码表示:移除index.html的<html>标签上的class="skins"样式} else {//此时为换肤状态,添加html的skins样式document.documentElement.classList.add('skins'); //该段代码表示:添加index.html的<html>标签上的class="skins"样式}
}

4.1 动态添加class

通过classList.remove和classList.add添加移除class类名

4.2 持久化

持久化:通过localStorage本地缓存主题变量名称即可
目的:1.刷新浏览器,保留主题变量即保留主题色
2.其他页面方便获取主题色变量;用于判断实现差异化等功能

5. 组件引入

在src/layout/layHeader.vue文件引入

<el-button @click="toggleTheme">{{ currentTheme === "light" ? "模式1" : "模式2" }}
</el-button>import { currentTheme, toggleTheme } from '../utils/theme'

6. main.js初始化主题色

解决刷新后主题色丢失问题

import { applyTheme } from '../utils/theme'
applyTheme(localStorage.getItem('app_theme'))

二、 涉及变更

1. element-plus、vxe-table、antv/g6、echarts等第三方组件库

组件、hover效果、disabled效果、tips、弹框、遮罩层、列表

2. 原生html

主要涉及到的前期,固定写死的class和style固定样式;
例如:
• 列表的链接项样式
• .wbg类名样式
使用css变量统一修改

3. 背景图

需要提供明暗两套背景图;通过主题变量名称currentTheme区分判断

三、其他换色思路

1.主题方式

参考链接
参考链接

2.别的博主实现方式

参考2

相关文章:

  • uniapp-商城-74-shop(7-商品列表,选规格 添加商品到购物车)
  • win10 pip安装插件包报错:No matching distribution found for pytest-xlsx
  • Allegro X PCB设计小诀窍--05.如何在Allegro X中实现隐藏电源飞线效果
  • SpringBoot的java应用中,慢sql会导致CPU暴增吗
  • ActiveMQ 可观测性最佳实践
  • 3D LUT--颜色魔方
  • jenkins配置ssh server通过ssh自动上传构建文件及执行脚本
  • 谈一谈我对强化学习的理解
  • TCP连接数统计脚本
  • 自动生成程序的heap文件
  • 基于CATIA参数化圆锥建模的自动化插件开发实践——NX建模之圆锥体命令的参考与移植(三)
  • B2146 Hermite 多项式
  • 简历中项目经历怎么写?
  • AI--知识库RAG实战
  • 手写字魔法消除1:数据集说明(含下载链接)
  • 让DeepSeek去除AI痕迹的指令
  • 高并发订单服务库存超卖解决方案
  • Python常用模块实用指南
  • Agent 的7 中设计模式
  • web端 firebase google analytics使用,入门级
  • 网站支持ipv6怎么做/360广告投放平台
  • 怎么做租房网站/精准营销系统
  • 医疗网站建设行业现状和影响/培训机构
  • 网站的百度百科怎么做/建网站赚钱
  • 在网上做效果图赚钱的网站/网店运营推广中级实训
  • 适合个人站长的网站有哪些/win7优化大师好不好