element主题色切换

2023-11-16

在网上搜了很多主题切换方案,发现没有适合自己项目的,不得已结合根据实际情况做一个子主题切换的功能。其中参考了element 官方的theme-chalk-preview,感兴趣的可以自己研究一下

主要功能是基于less切换主题色,可以自定义颜色,同时结合VuexlocalStorage对主题色进行缓存,在下次进入项目时初始化

代码地址:theme-chalk-preview代码
预览地址:theme-chalk-preview预览

首先说一下我的项目环境:

  • Vue: 2.6.10
  • Less: 3.9.0
  • Element: 2.15.6
  • css-color-function: 1.3.3

代码编写

  • 由于项目需要对主题色进行缓存,所以主要代码编写在Vueapp.vue文件下,以确保在初始化时能及时获取主题色配置

1. Vuex相关

state: {
	theme: localStorage.getItem('theme') || '#409EFF',
  	originalStyle: ''
 }
mutations: {
  // 设置主题颜色
  setTheme(state, color) {
    state.themeColor = color;
	localStorage.setItem('themeColor', color);
  },
  // 获取element 默认样式文件
  setStyle(state, data) {
    state.originalStyle = data
  },
}
getters: {
  theme: state => state.theme,
  originalStyle: state => state.originalStyle
}

Vuex中声明了两个变量,然后通过mutations和getters对变量进行获取和赋值


1、theme,表示当前主题色,由于是存储在localStorage中的,所以先从localStorage中获取,然后才是基准色,我的基准色采用的是Element的默认颜色#409eff


2、originalStyle,这个变量存放的是element某个主题颜色的基础样式文件(element-ui的默认样式文件),其实本次主题切换的实质就是在element的基础样式文件上进行,通过修改该文件中的颜色值来切换主题。放在vuex中的目的是我的需求中有多个地方可以切换主题色,方便获取,以免重复下载样式文件

2.新建color工具函数文件(用来替换主题样式文件中的颜色值)

//   util/color.js
import color from 'css-color-function'

// 基于 primary变量 生成颜色键值对
const formula = {
  "shade-1": "color(primary shade(10%))",
  "light-1": "color(primary tint(10%))",
  "light-2": "color(primary tint(20%))",
  "light-3": "color(primary tint(30%))",
  "light-4": "color(primary tint(40%))",
  "light-5": "color(primary tint(50%))",
  "light-6": "color(primary tint(60%))",
  "light-7": "color(primary tint(70%))",
  "light-8": "color(primary tint(80%))",
  "light-9": "color(primary tint(90%))"
}

const generateColors = primary => {
  let colors = {}

  Object.keys(formula).forEach(key => {
  	// 此处通过传入的primary颜色将formula对象中的值转换成RGB格式的颜色
    const value = formula[key].replace(/primary/g, primary)
    // 设置RGB颜色值
    colors[key] = color.convert(value)
  })
  return colors
}
/** eg: 

	const colors = generateColor('#409eff')
	colos => {
	    "shade-1": "rgb(58, 142, 230)",
	    "light-1": "rgb(83, 168, 255)",
	    "light-2": "rgb(102, 177, 255)",
	    "light-3": "rgb(121, 187, 255)",
	    "light-4": "rgb(140, 197, 255)",
	    "light-5": "rgb(160, 207, 255)",
	    "light-6": "rgb(179, 216, 255)",
	    "light-7": "rgb(198, 226, 255)",
	    "light-8": "rgb(217, 236, 255)",
	    "light-9": "rgb(236, 245, 255)"
	}
	
*/
export default generateColors

3.App.vue文件

  • 声明color变量:
data() {
	return {
		colors: {
			primary: "", // 默认颜色
		},
	};
},
  • 引入generateColors方法:
import generateColors from "@/util/color";
  • 获取vuex中声明的变量
import { mapGetters, mapMutations} from "vuex";
export default {
	computed: {
		...mapGetters(["themeColor", "originalStyle"]),
	},
	methods: {
		...mapMutations(['setStyle', 'setTheme']),
	}
}
  • 下载css文件并替换文件中的颜色值:
export default {
	methods: {
		...mapMutations(['setStyle', 'setTheme']),
		// 该方法是将样式文件中的颜色值替换成键值对中的value(primary、light-n、shade-1)
		getStyleTemplate(data) {
			// 具体颜色值可参考上面提到的官方案例theme-chalk-preview
			const colorMap = {
				"#3a8ee6": "shade-1",
				"#409eff": "primary",
				"#53a8ff": "light-1",
				"#66b1ff": "light-2",
				"#79bbff": "light-3",
				"#8cc5ff": "light-4",
				"#a0cfff": "light-5",
				"#b3d8ff": "light-6",
				"#c6e2ff": "light-7",
				"#d9ecff": "light-8",
				"#ecf5ff": "light-9",
			};
			Object.keys(colorMap).forEach((key) => {
				const value = colorMap[key];
				data = data.replace(new RegExp(key, "ig"), value);
			});
			return data;
		},
		// 主方法,可在页面内初始化的时候请求
		getIndexStyle() {
			// 这里可以根据自己的element版本下载指定版本
			this.getFile(
				`//unpkg.com/element-ui@2.15.6/lib/theme-chalk/index.css`
			).then(({ data }) => {
				// 进行颜色值替换,同时将替换后的样式文件保存到vuex中,方便其他地方获取(按你自己的需求来存放)
				this.setStyle(this.getStyleTemplate(data));
				// 根据传入的themeColor生成颜色键值对
				this.colors = Object.assign(
					this.colors,
					generateColors(this.themeColor)
				);
				// 生成样式文件插入到页面根节点
				this.writeNewStyle();
			});
		},
		// 传入url,下载指定样式文件
		getFile(url, isBlob = false) {
			return new Promise((resolve, reject) => {
				const client = new XMLHttpRequest();
				client.responseType = isBlob ? "blob" : "";
				client.onreadystatechange = () => {
					if (client.readyState !== 4) {
						return;
					}
					if (client.status === 200) {
						const urlArr = client.responseURL.split("/");
						resolve({
							data: client.response,
							url: urlArr[urlArr.length - 1],
						});
					} else {
						reject(new Error(client.statusText));
					}
				};
				client.open("GET", url);
				client.send();
			});
		},
	}
	writeNewStyle() {
		// 这里获取到的cssText是将文件中的颜色值替换为(primary、light-n、shade-1)过后的
		let cssText = this.originalStyle;
		/** 
			此时this.colors的值为:
			{
			    "primary": "#409eff",
			    "shade-1": "rgb(58, 142, 230)",
			    "light-1": "rgb(83, 168, 255)",
			    "light-2": "rgb(102, 177, 255)",
			    "light-3": "rgb(121, 187, 255)",
			    "light-4": "rgb(140, 197, 255)",
			    "light-5": "rgb(160, 207, 255)",
			    "light-6": "rgb(179, 216, 255)",
			    "light-7": "rgb(198, 226, 255)",
			    "light-8": "rgb(217, 236, 255)",
			    "light-9": "rgb(236, 245, 255)"
			}
			然后再将cssText中的(primary、light-n、shade-1)替换成当前主题色的颜色值
		*/
		Object.keys(this.colors).forEach((key) => {
			cssText = cssText.replace(
				new RegExp("(:|\\s+)" + key, "g"),
				"$1" + this.colors[key]
			);
		});
		// 接下来在dom插入样式文件
		let styleTag = document.getElementById("chalk-style");
		if (!styleTag) {
			styleTag = document.createElement("style");
			styleTag.innerText = cssText;
			styleTag.setAttribute("id", "chalk-style");
			document.head.appendChild(styleTag);
			} else {
				styleTag.innerText = cssText;
			}
			this.$store.commit("setTheme", this.colors.primary);
		},
	},
}
  • 修改成功后可以在head进行查看
    img1
  • 展开找到我们之前声明id为chalk-style的style文件,到这里已经修改完成了
    img2
  • 这时候如果要更改主题色,只需要修改color.primary的值就行了
export default {
	created() {
		this.colors.primary = this.themeColor;
		this.getIndexStyle();
	},
}

app.vue完整代码

<template>
	<div id="app">
		<router-view/>
	</div>
</template>
<script>
import { mapGetters, mapMutations } from "vuex";
import generateColors from "@/util/color";
export default {
	data() {
		return {
			colors: {
				primary: "",
			},
		};
	},
	computed: {
		...mapGetters(["themeColor", "originalStyle"]),
	},
	created() {
		this.colors.primary = this.themeColor;
		this.getIndexStyle();
	},
	methods: {
    	...mapMutations(['setStyle', 'setTheme']),
		getStyleTemplate(data) {
			const colorMap = {
				"#3a8ee6": "shade-1",
				"#409eff": "primary",
				"#53a8ff": "light-1",
				"#66b1ff": "light-2",
				"#79bbff": "light-3",
				"#8cc5ff": "light-4",
				"#a0cfff": "light-5",
				"#b3d8ff": "light-6",
				"#c6e2ff": "light-7",
				"#d9ecff": "light-8",
				"#ecf5ff": "light-9",
			};
			Object.keys(colorMap).forEach((key) => {
				const value = colorMap[key];
				data = data.replace(new RegExp(key, "ig"), value);
			});
			return data;
		},
		getIndexStyle() {
			this.getFile(
				`//unpkg.com/element-ui@2.15.6/lib/theme-chalk/index.css`
			).then(({ data }) => {
        	this.setStyle(this.getStyleTemplate(data))
				this.colors = Object.assign(
					this.colors,
					generateColors(this.themeColor)
				);
				this.writeNewStyle();
			});
		},
		getFile(url, isBlob = false) {
			return new Promise((resolve, reject) => {
				const client = new XMLHttpRequest();
				client.responseType = isBlob ? "blob" : "";
				client.onreadystatechange = () => {
					if (client.readyState !== 4) {
						return;
					}
					if (client.status === 200) {
						const urlArr = client.responseURL.split("/");
						resolve({
							data: client.response,
							url: urlArr[urlArr.length - 1],
						});
					} else {
						reject(new Error(client.statusText));
					}
				};
				client.open("GET", url);
				client.send();
			});
		},
		writeNewStyle() {
			let cssText = this.originalStyle;
			Object.keys(this.colors).forEach((key) => {
				cssText = cssText.replace(
					new RegExp("(:|\\s+)" + key, "g"),
					"$1" + this.colors[key]
				);
			});
			let styleTag = document.getElementById("chalk-style");
			if (!styleTag) {
				styleTag = document.createElement("style");
				styleTag.innerText = cssText;
				styleTag.setAttribute("id", "chalk-style");
				document.head.appendChild(styleTag);
			} else {
				styleTag.innerText = cssText;
			}
      		this.setTheme(this.colors.primary)
		},
	},
};
</script>
<style lang="less">
</style>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

element主题色切换 的相关文章

随机推荐

  • UVA 10970 - Big Chocolate

    Root AOAPC I Beginning Algorithm Contests Training Guide Rujia Liu UVA 10970 Big Chocolate 题意 计算将一块n m的巧克力切成n m块所需的次数 方法
  • Android studio报错:e: org.jetbrains.kotlin.codegen.CompilationException: Back-end (JVM) Internal error

    Android studio运行时报错 e org jetbrains kotlin codegen CompilationException Back end JVM Internal error wrong bytecode gener
  • mtu设置--解决部分网站打不开的问题

    资料一 一 常见问题介绍 1 什么情况下需要改MTU 如果您的动态域名网站不能被正常访问 很难连接 连接上也非常慢 请试试把DirectSend设为 总是关闭 如果关闭后可以正常访问 这种情况就需要修改MTU 如果您的网站连接正常 只是下载
  • 达尔文商品体系

    一 背景介绍 最初是由天猫发起的 针对天猫品牌混乱 原始商品信息错误和商家重复铺货 商家的宝贝 库存价格等信息杂乱无章 商家发布商品流程冗长 管理商品非常不便 消费者也很难找到确定的商品相关信息 前台的搜索应用困难等问题 旨在规范商品信息确
  • 批量爬虫采集大数据的技巧和策略分享

    作为一名专业的爬虫程序员 今天主要要和大家分享一些技巧和策略 帮助你在批量爬虫采集大数据时更高效 更顺利 批量爬虫采集大数据可能会遇到一些挑战 但只要我们掌握一些技巧 制定一些有效的策略 我们就能在数据采集的道路上一帆风顺 1 设立合理的请
  • 服务器虚拟机无法连接msk,无法连接mks【图文详解】

    喜欢使用电脑的小伙伴们一般都会遇到win7系统无法连接mks的问题 突然遇到win7系统无法连接mks的问题就不知道该怎么办了 其实win7系统无法连接mks的解决方法非常简单 按照1 首先检查了下 windows的防火墙设置 可以看到Vm
  • QT笔记——QProcess学习

    我们常常想通过某一个类 来启动一个外部进程 本文将讲解如何通过QProcess来进行启动外部进程 一 了解QProcess QProcess是Qt框架提供的一个类 用于在应用程序中执行外部进程 它提供了一系列函数来启动 控制和与外部进程进行
  • axios请求超时

    axios请求超时 设置重新请求的完美解决方法 自从使用Vue2之后 就使用官方推荐的axios的插件来调用API 在使用过程中 如果服务器或者网络不稳定掉包了 你们该如何处理呢 下面我给你们分享一下我的经历 具体原因 最近公司在做一个项目
  • Spring Cloud Gateway学习

    文章大纲 为什么需要网关 传统的单体架构只有一个服务开放给客户端调用 但是在微服务架构体系中是将一个系统拆分成多个微服务 那么作为客户端如何去调用这些微服务呢 如果没有网关的存在 就只能在本地记录每个微服务的调用地址 无网关的微服务架构存在
  • C++之MFC学习

    问题1 stdafx h是怎么引入进来的 define h与stdafx h之间的关系 为什么在MuisicPlayer cpp中引入stdafx h 问题2 enum class的使用 问题3 列表初始化 int window trans
  • linux重做系统分区,搜索所有硬盘分区上的linux系统,重新安装grub的方法

    电脑硬盘上 非vmware 安装了Ubuntu Fedora Debian openSUSE linuxMint Mageia elementaryOS PearOS ZorinOS Bodhi Manjaro Sparky linuxDe
  • 【星球精选】如何高效构建 Roam 与 theBrain 间细粒度双向链接?

    Roam Research 作为卡片盒很好用 只是目前缺乏中观网络可视化能力 老牌知识管理应用TheBrian 可以很好补充上这个短板 因此我希望将二者结合起来使用 只是这个过程 有些曲折 在 Obsidian 中的 excalibrain
  • redis可视工具AnotherRedisDesktopManager的使用

    redis可视工具AnotherRedisDesktopManager的使用 系列文章 macm1安装redis过程 springboot整合redis及set map list key value和实体类操作 redis可视工具Anoth
  • 龙书11_chapter_6 一:一般绘制流程

    先看BoxDemo的前几节 1 vertex input Layout 2 vertexBuffer 3 IndexBuffer 4 vertexShader 5 constant Buffer 6 pixelShader 7 render
  • Hbase存储及元数据meta

    Hbase的列族式存储 列族就是多个数据列的组合 列族式可以说是表的schema的一部分 而列不是 Hbase可以说是列簇数据库 在创建表的时候要指定列族 而不需要指定具体的列 Hbase Table组成 Table rowkey fami
  • Sqli-labs之Less-25和Less-25a

    Less 25 GET 基于错误 您所有的OR AND都属于我们 字符串单引号 Notice Undefined variable hint in C phpStudy WWW sqli Less 25 index php on line
  • Android自动化测试框架实现

    背景介绍 最近打算梳理一下不同产品领域的自动化测试实现方案 如 Android终端 Web 服务端 智能硬件等 就先从Android终端产品开始梳理吧 本文主要介绍UI自动化测试的实现 因为这类测试解决方案比较通用 Android系统层 内
  • CentOS 7下安装nginx+php+mysql

    目录 一 安装Nginx 1 安装make 2 安装g 3 安装PCRE库 4 安装zlib库 5 安装ssl 6 下载和解压nginx 7 添加nginx用户和用户组 8 配置nginx安装参数 9 编译并且安装nginx 10 启动ng
  • Windows下的mingw-Qt开发环境安装及helloworld实现

    Windows下的mingw Qt开发环境安装及helloworld实现 我用的是Qt5 7 因此本次总结是基于Qt5 7 0的 我在自学的时候使用的IDE是Qt自带的Qt creator 上手简单 配置属于自己顺手的设置很方便 此外 如果
  • element主题色切换

    在网上搜了很多主题切换方案 发现没有适合自己项目的 不得已结合根据实际情况做一个子主题切换的功能 其中参考了element 官方的theme chalk preview 感兴趣的可以自己研究一下 主要功能是基于less切换主题色 可以自定义