vue换肤

这篇博客介绍了如何在Vue.js应用中创建一个封装好的换肤组件,允许用户自定义主题颜色。通过监听颜色变化,更新全局样式,并将颜色值存储在localStorage中,实现换肤效果。同时,组件还包含了颜色验证、颜色集群处理等功能,确保颜色值的正确性和一致性。
摘要由CSDN通过智能技术生成

封装好的换肤组件

<template>
	<el-color-picker v-model="theme" class="theme-picker" 
		popper-class="theme-picker-dropdown">
	</el-color-picker>
</template>

<script>
	const version = require("element-ui/package.json").version; // 版本号
	const ORIGINAL_THEME = "#409EFF";

	export default {
		name: "colorPicker",
		data() {
			return {
				chalk: "",
				theme: "#409EFF",
			};
		},
		mounted() {
			// if (this.CheckIsColor(localStorage.getItem("colorPicker"))) {
			// 	// this.theme = localStorage.getItem("colorPicker");
			// }
		},
		watch: {
			theme(val, oldVal) {
				this.$message.success("换肤成功"); //需要提示则可以不用去除,不需要提示则去除或注释
				if (typeof val !== "string") return;
				localStorage.setItem("colorPicker", val);
				const themeCluster = this.getThemeCluster(val.replace("#", ""));
				const originalCluster = this.getThemeCluster(oldVal.replace("#", ""));
				const getHandler = (variable, id) => {
					return () => {
						const originalCluster = this.getThemeCluster(
							ORIGINAL_THEME.replace("#", "")
						);
						const newStyle = this.updateStyle(
							this[variable],
							originalCluster,
							themeCluster
						);

						let styleTag = document.getElementById(id);
						if (!styleTag) {
							styleTag = document.createElement("style");
							styleTag.setAttribute("id", id);
							document.head.appendChild(styleTag);
						}
						styleTag.innerText = newStyle;
					};
				};

				const chalkHandler = getHandler("chalk", "chalk-style");

				if (!this.chalk) {
					const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`;
					this.getCSSString(url, chalkHandler, "chalk");
				} else {
					chalkHandler();
				}

				const styles = [].slice
					.call(document.querySelectorAll("style"))
					.filter(style => {
						const text = style.innerText;
						return (
							new RegExp(oldVal, "i").test(text) && !/Chalk Variables/.test(text)
						);
					});
				styles.forEach(style => {
					const {
						innerText
					} = style;
					if (typeof innerText !== "string") return;
					style.innerText = this.updateStyle(
						innerText,
						originalCluster,
						themeCluster
					);
				});
				/* 当颜色改变时,使用vuex储存改变的颜色值 */
				
			}
		},

		methods: {
			CheckIsColor(bgVal) {
				var type = "^#[0-9a-fA-F]{6}$";
				var re = new RegExp(type);
				if (bgVal.match(re) == null) {
					type =
						// eslint-disable-next-line no-useless-escape
						"^[rR][gG][Bb][\(]([\\s]*(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?)[\\s]*,){2}[\\s]*(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)[\\s]*[\)]{1}$";
					re = new RegExp(type);
					if (bgVal.match(re) == null) {
						return false;
					} else {
						return true;
					}
				} else {
					return true;
				}
			},
			updateStyle(style, oldCluster, newCluster) {
				let newStyle = style;
				oldCluster.forEach((color, index) => {
					newStyle = newStyle.replace(new RegExp(color, "ig"), newCluster[index]);
				});
				return newStyle;
			},

			getCSSString(url, callback, variable) {
				const xhr = new XMLHttpRequest();
				xhr.onreadystatechange = () => {
					if (xhr.readyState === 4 && xhr.status === 200) {
						this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, "");
						callback();
					}
				};
				xhr.open("GET", url);
				xhr.send();
			},

			getThemeCluster(theme) {
				const tintColor = (color, tint) => {
					let red = parseInt(color.slice(0, 2), 16);
					let green = parseInt(color.slice(2, 4), 16);
					let blue = parseInt(color.slice(4, 6), 16);

					if (tint === 0) {
						// when primary color is in its rgb space
						return [red, green, blue].join(",");
					} else {
						red += Math.round(tint * (255 - red));
						green += Math.round(tint * (255 - green));
						blue += Math.round(tint * (255 - blue));

						red = red.toString(16);
						green = green.toString(16);
						blue = blue.toString(16);

						return `#${red}${green}${blue}`;
					}
				};

				const shadeColor = (color, shade) => {
					let red = parseInt(color.slice(0, 2), 16);
					let green = parseInt(color.slice(2, 4), 16);
					let blue = parseInt(color.slice(4, 6), 16);

					red = Math.round((1 - shade) * red);
					green = Math.round((1 - shade) * green);
					blue = Math.round((1 - shade) * blue);

					red = red.toString(16);
					green = green.toString(16);
					blue = blue.toString(16);

					return `#${red}${green}${blue}`;
				};

				const clusters = [theme];
				for (let i = 0; i <= 9; i++) {
					clusters.push(tintColor(theme, Number((i / 10).toFixed(2))));
				}
				clusters.push(shadeColor(theme, 0.1));
				return clusters;
			}
		}
	};
</script>

<style>
	.theme-picker .el-color-picker__trigger {
		vertical-align: middle;
	}

	.theme-picker-dropdown .el-color-dropdown__link-btn {
		display: none;
	}
</style>

在需要引入该组件的位置注册该组件

例如:


在需要引用的组件上注册该组件并使用
<themeCom :color="color" @color-update="colorChange" />
在components:{
	themeCom   //在components中注册该组件
}

在data数据中添加:
color: "#409EFF",


在方法中使用:
//点击改变全局颜色
    colorChange(color) {
      this.color = color;
    },
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值