在vue3页面自定义主题,element-puls的scss的底层原因

 element-puls的颜色的原理,由于要给我们先定义好不同的主题色,所以肯定不可能一模一样,不过大体的流程是这样子,

不过先说明一下,修改主题色并没有太好的方法,最终的方法都是用 js 覆盖ui组件库的 最重要的主题色 ( primart系列 ) 从而达到动态主题色的效果

我也想过用 js 修改scss的变量,但是这样根本行不通,因为scss的函数和方法只能用scss的变量,而想修改scss变量需要套一层css的变量,如:

$aaa:var(--my-color,red)
//然后
 document.documentElement.style.setProperty("--my-color", '#626aef');

但是这样scss就函数和方法识别不了,

因为var()是css的,scss根本不会编译,会把 var(--my-color,red) 当成一个值

所以只能用js把新的变量覆盖旧的变量.

当然如果你有更好的方法(用最少的js代码)实现动态主题色变化可以留言

 如果你想用来做自己的自定义主题,前面的几个带有 !default 参数都可以修改,其中最重要的就是 $default-theme-arr 变量,

如果你深入了解,还可以修改里面的参数,达到更多的颜色

 把下面的写入scss文件再引入到main.ts

@use "sass:math";
@use "sass:map";
// 你要的颜色(key值不能为颜色,英文表示的颜色也不行,但是可以isviolet)
$default-theme-arr: (
	isviolet: #626aef,
	iscolour: #41b584,
	isblue:#409eff,
	isred:#f34d37,
) !default;
// 你的空间命名(前缀)
$namespace: "my" !default;
// 你的混入白  (会影响到light系列相关的颜色)
$mix-white-color: #ffffff !default;
// 你的混入黑 (会影响到dark系列相关的颜色)
$mix-black-color: #141414 !default;
//最终的light层级,element默认为 3, 5, 7, 8, 9(需要整数)
$light-tier: (3, 5, 7, 8, 9) !default;


// keys和values
$default-theme-keys: map.keys($default-theme-arr);
$default-theme-values: map.values($default-theme-arr);

// 自定义scss变量
$default-theme: () !default;
@each $type in $default-theme-keys {
	$default-theme: map.deep-merge(
		(
			$type: (
				"base": map.get($default-theme-arr, $type),
			),
		),
		$default-theme
	) !global;
}
// https://sass-lang.com/documentation/values/maps#immutability
//用白/黑混合颜色来产生亮/暗的层次
@mixin set-color-mix-level($type, $mode, $number, $mix-color) {
	$default-theme: map.deep-merge(
		(
			$type: (
				// light-$i:混合(混合的颜色,被混合的颜色,混合多少)
				// mix($color1, $color2, $weight) 表示$color1的比例为$weight,$color2的比例为1-$weight
				// math.转百分比(math.转分数(分子,分母)) 
				// 		如 math.percentage(math.div(2, 10)) => math.percentage(0.2) => 20%
				// 最终混合出的颜色为:白或黑为20%,传进来的颜色为剩余的80%
				"#{$mode}-#{$number}":
					mix(
						$mix-color,
						map.get($default-theme, $type, "base"),
						math.percentage(math.div($number, 10))
					),
			),
		),
		$default-theme
	) !global;
}

// css变量名
@function joinVarName($list) {
	$name: "--" + $namespace; //前缀
	// 遍历变量名 并返回
	@each $item in $list {
		@if $item != "" {
			$name: $name + "-" + $item;
		}
	}
	@return $name;
}
//设置CSS var值,因为我们需要将value转换为字符串
//例如:@include set-css-var-value(('color', 'primary'), red);
// --el-color-primary:红色;
@mixin set-css-var-value($name, $value) {
	#{joinVarName($name)}: #{$value};
}

// 添加不同的变量颜色
// light 系列     $colors.primary.light-i
@each $type in $default-theme-keys {
	@for $i from 1 through 9 {
		@include set-color-mix-level($type, "light", $i, $mix-white-color);
	}
}
// dark 系列      $colors.primary.light-i
@each $type in $default-theme-keys {
	@for $i from 1 through 9 {
		@include set-color-mix-level($type, "dark", $i, $mix-black-color);
	}
}
// 自定义颜色
:root {
	@for $ii from 1 through length($default-theme-arr) {
		$this-key: nth($default-theme-keys, $ii);
		$this-value: nth($default-theme-values, $ii);

		@include set-css-var-value(
			($this-key, "rgb"),
			(red($this-value), green($this-value), blue($this-value))
		);
		@include set-css-var-value($this-key, $this-value);
		@each $i in $light-tier {
			@include set-css-var-value(
				($this-key, "light", $i),
				map.get($default-theme, $this-key, "light-#{$i}")
			);
		}
		@include set-css-var-value(
			($this-key, "dark-2"),
			map.get($default-theme, $this-key, "dark-2")
		);
	}
}
// 黑暗模式
html.dark {
	@for $ii from 1 through length($default-theme-arr) {
		$this-key: nth($default-theme-keys, $ii);
		$this-value: nth($default-theme-values, $ii);

		@include set-css-var-value(
			($this-key, "rgb"),
			(red($this-value), green($this-value), blue($this-value))
		);
		@include set-css-var-value($this-key, $this-value);
		@each $i in $light-tier {
			@include set-css-var-value(
				($this-key, "light", $i),
				map.get($default-theme, $this-key, "dark-#{$i}")
			);
		}
		@include set-css-var-value(
			($this-key, "dark-2"),
			map.get($default-theme, $this-key, "dark-2")
		);
	}
}

变量颜色效果:

 修改主题颜色

<template>
<el-select v-model="TopicAcitve">
	<el-option
		class="option"
		v-for="item in Topic"
		:key="item.value"
		:label="item.label"
		:value="item.value" />
    </el-select>
</template>
<script setup lang="ts">
// 主题色(参数只能是 scss文件你写的 $default-theme-arr里面的key值)
let Topic: ref([
    { label: '主题蓝', value: 'isblue' },
    { label: '主题绿', value: 'iscolour' },
    { label: '主题红', value: 'isred' },
    { label: '主题紫', value: 'isviolet' }
]),
let TopicAcitve = ref('isblue')


const style = document.documentElement.style;
//监听用户有没有修改主题色
watch(() => TopicAcitve.value,(newVal) => {
		style.setProperty("--el-color-primary-rgb", `var(--my-${themeColor}-rgb)`);
		style.setProperty("--el-color-primary", `var(--my-${themeColor})`);
		style.setProperty("--el-color-primary-light-3", `var(--my-${themeColor}-light-3)`);
		style.setProperty("--el-color-primary-light-5", `var(--my-${themeColor}-light-5)`);
		style.setProperty("--el-color-primary-light-7", `var(--my-${themeColor}-light-7)`);
		style.setProperty("--el-color-primary-light-8", `var(--my-${themeColor}-light-8)`);
		style.setProperty("--el-color-primary-light-9", `var(--my-${themeColor}-light-9)`);
		style.setProperty("--el-color-primary-dark-2", `var(--my-${themeColor}-dark-2)`);
});
</script>

效果图

内容不一样,用的代码是一样的

20230222_112753

猜你喜欢

转载自blog.csdn.net/weixin_59916662/article/details/129137764