组件库从开发到维护全链路讲解(三)小型组件换肤的最佳实践
本篇文章为《前端组件库的开发与维护》系列的第三篇文章。本文案例在线文档:calendar.hxkj.vip。GitHub 仓库:github.com/TangSY/vue3…。
今天主要讲解如何在一个小型的组件库当中实现换肤功能。其实呢,之前也写过类似的文章《大型复杂项目中使用 antd 最新特性实现运行时低成本动态换肤》,当时是针对大型 React
项目所给出的方案,并不一定适合小型组件库。方案本身没有优劣,最适合的就是最好的。
方案及实现
方案
主题换肤功能,从大方向上来看,无非就是两种方案:
- 静态换肤:由开发者在系统中内置一些主题样式或者颜色供使用方选择。这种方案可选项比较有限,适用于
TO C
平台提供给用户整套系统的换肤功能。因为大部分用户其实是没有很好的配色艺术细胞的,过于开放的话,容易把系统搞的不堪入目。这时就需要平台提供几套预设的皮肤给用户选择。 - 动态换肤:支持任意配色,哪个地方用什么颜色完全由用户控制,例如直接给用户提供一个调色板,让他自己玩去。并且这种方式非常适合用于组件,因为作为组件提供方来说,无法预知组件使用方面对的需求,所以得提供支持完全自定义的方案,让其根据具体的需求来配色。
Thus,我们选择了动态换肤的方案。再深入一点的话,得从具体的技术选型来确定我们的最终方案。在这里就不一一对比市面上现存的换肤方案了,类似的文章有很多,基本上都大同小异。这边给个参考文章《前端换肤的N种方案,请收下》。
看过上面那个参考文章之后,相信大家对换肤的几种方案有了大致的了解了。由于这个组件是基于 Vue3
开发的,其本身已经放弃一部分兼容性了,很好!省事了!不用去关心兼容性的问题。因此,答案已经呼之欲出了——Css Variables
。有同学可能就要问了,那你咋保证支持 Vue3
就一定支持 Css Variables
呢?那咱们就拿两张从 Can I Use 中截下来的兼容性图来对比下,有图有真相!
由于本组件就是用于移动端的,所以咱们只看右边移动端的兼容性对比就可以了。可以看到,兼容性没有任何差别,那也就意味着只要你能用 Vue3
就一定能用 Css Variables
。
实现
好了,方案讨论完毕了,接下来进入到 Coding 环节。
首先定义一个存放默认 css 变量和 less 变量的 less 文件。咦?为啥我用了css 变量还要用 less 变量?没别的原因,只是为了方便在内部不同的组件之间引用而已。这个文件可以放在入口文件引入,这样的话里面的 less 变量就可以全局使用了。
@default-main-color: #1c71fb;
@default-bg-color: #f4f4f4;
@default-main-font-color: #4c4c4c;
@default-vice-font-color: #898989;
@default-disabled-bg-color: #f5f7fa;
@default-disabled-font-color: #c0c4cc;
@default-range-middle-background-opacity: 0.1;
:root {
--hash-calendar-main-color: @default-main-color;
--hash-calendar-bg-color: @default-bg-color;
--hash-calendar-main-font-color: @default-main-font-color;
--hash-calendar-vice-font-color: @default-vice-font-color;
--hash-calendar-disabled-bg-color: @default-disabled-bg-color;
--hash-calendar-disabled-font-color: @default-disabled-font-color;
--hash-calendar-range-middle-background-opacity: @default-range-middle-background-opacity;
}
// 页面主色
@main-color: var(--hash-calendar-main-color, @default-main-color);
// 页面背景色
@bg-color: var(--hash-calendar-bg-color, @default-bg-color);
// 主文字颜色
@main-font-color: var(--hash-calendar-main-font-color, @default-main-font-color);
// 副文字颜色
@vice-font-color: var(--hash-calendar-vice-font-color, @default-vice-font-color);
// 禁用背景颜色
@disabled-bg-color: var(--hash-calendar-disabled-bg-color, @default-disabled-bg-color);
// 禁用文字颜色
@disabled-font-color: var(--hash-calendar-disabled-font-color, @default-disabled-font-color);
那如何使用呢?接着往下看。
在写样式的时候,就跟平常引用 less
变量没啥区别。例如:
.calendar {
color: @main-color;
background: @bg-color;
}
目前为止,咱们的组件只支持使用默认配色,接下来我们需要暴露一个 props
属性,让其接受使用方传进来的配色,达到动态换肤的目的。
// props 类型定义
type ThemeColorType = {
'main-color': string;
'bg-color': string;
'main-font-color': string;
'vice-font-color': string;
'disabled-bg-color': string;
'disabled-font-color': string;
};
// props 属性定义
themeColor: {
type: Object as PropType<ThemeColorType>,
default: () => ({}),
}
然后是 js
处理部分,定义一个 getThemeColor
方法,返回 Css Variables
对象,让其可以直接绑定在 style
上。
// 获取主题颜色
const getThemeColor = () => {
const cssVar: any = {};
if (props.themeColor) {
const themeColorKeys = Object.keys(props.themeColor || {}) as Array<keyof ThemeColorType>;
if (themeColorKeys.length) {
themeColorKeys.forEach((k) => {
// 添加组件特有前缀
cssVar[`--hash-calendar-${k}`] = props.themeColor[k];
});
}
}
return cssVar;
};
然后在 dom render
中使用该方法即可:
<div class="hash-calendar" style={{...getThemeColor()}} >
...
</div>
使用效果:
体验地址:calendar.hxkj.vip/#/theme-col…
总结
到此,日历组件的主体换肤功能的讲解就告一段落了,是不是看起来挺简单的,不费吹灰之力就完成了动态换肤功能,还是那句话:最适合的就是最好的。下篇咱们一起来看看组件单元测试用例的编写思路。
对此系列感兴趣的,不妨一键三连(点赞 + 关注 + 收藏),方便跟进后续文章。
欢迎大家在评论区留下宝贵的建议!
本系列往期文章
转载自:https://juejin.cn/post/7190563104990691389