需求
最近做的公共模块,需要提供给不同平台,可以通过传参实现主题色的适配,目前支持模板一键换肤以及自定义换肤。
实现方案
换肤方案主要是基于CSS自定义变量以及sass动态修改data-theme实现的。
模板换肤
首先提供几套主题色模板,统一放在theme文件夹当中。
blue.scss (默认主题)
$blue: (
// 字体
font_color: #00a5e5,
// 按钮背景
background_color: #00a5e5,
// 鼠标划过
background_hover_color: #0094CE,
// 禁用
background_disable_color:#CCEDFA,
// 边框颜色
border_color: #00a5e5,
)
复制代码
your.scss (你的主题)
$ucode-website: (
// 字体
font_color: #7284fb,
// 按钮背景
background_color: #7284fb,
// 鼠标划过
background_hover_color: #6676E1,
// 禁用
background_disable_color: #E6EAFF,
// 边框颜色
border_color: #7284fb,
)
复制代码
adapt-theme.scss (主题适配器)
@import './theme.scss';
@import './themes/default.scss';
// 遍历主题
@mixin themeify {
@each $theme-name, $theme-map in $themes {
// !global 把局部变量强升为全局变量
$theme-map: $theme-map !global;
[data-theme="#{$theme-name}"] & {
@content;
}
}
}
// 根据Key值获取颜色
@function themed($key) {
@return map-get($theme-map, $key);
}
// 获取字体颜色
@mixin font_color($color) {
@include themeify{
color: themed($color);
}
}
// 获取边框颜色
@mixin border_color($color) {
@include themeify{
border-color: themed($color);
}
}
// 获取背景颜色
@mixin background_color($color) {
@include themeify{
background-color: themed($color);
}
}
// 鼠标划过
@mixin background_hover_color($color) {
@include themeify{
background-color: themed($color);
}
}
// 禁用
@mixin background_disable_color($color) {
@include themeify{
background-color: themed($color);
}
}
复制代码
调用主题模板
第三方调用时传主题参数到公共模块,写入顶层元素的data-theme即可自动适配模板。
<div data-theme={this.context.theme}></div>
复制代码
适配公共组件
@import "../../../styles/adapt-theme.scss";
button {
@include background_color("background_color");
}
复制代码
自定义颜色换肤
定义初始CSS变量,挂载在根元素,可以全局使用。
:root {
--fontColor: initial; // 此处注意,initial才为空值
--backgroundColor: initial;
--backgroundHoverColor: initial;
--backgroundDisableColor: initial;
--borderColor: initial;
}
复制代码
第三方调用传参后,JS动态修改CSS变量。
const body = document.getElementsByTagName('body')[0];
const { themeStyles } = this.context;
for (const style in themeStyles) {
if (themeStyles[style]) {
body.style.setProperty(`--${style}`, themeStyles[style]);
}
}
复制代码
最后修改主题适配器,利用CSS无效变量,可以实现自定义变量覆盖模板,当没有自定义变量时,又不会影响模板渲染。这个是关键。
// 获取字体颜色
@mixin font_color($color) {
@include themeify{
color: var(--fontColor, themed($color));
}
}
复制代码