likes
comments
collection
share

组件库从开发到维护全链路讲解(三)小型组件换肤的最佳实践

作者站长头像
站长
· 阅读数 22

本篇文章为《前端组件库的开发与维护》系列的第三篇文章。本文案例在线文档:calendar.hxkj.vip。GitHub 仓库:github.com/TangSY/vue3…

今天主要讲解如何在一个小型的组件库当中实现换肤功能。其实呢,之前也写过类似的文章《大型复杂项目中使用 antd 最新特性实现运行时低成本动态换肤》,当时是针对大型 React 项目所给出的方案,并不一定适合小型组件库。方案本身没有优劣,最适合的就是最好的。

方案及实现

方案

主题换肤功能,从大方向上来看,无非就是两种方案:

  1. 静态换肤:由开发者在系统中内置一些主题样式或者颜色供使用方选择。这种方案可选项比较有限,适用于 TO C 平台提供给用户整套系统的换肤功能。因为大部分用户其实是没有很好的配色艺术细胞的,过于开放的话,容易把系统搞的不堪入目。这时就需要平台提供几套预设的皮肤给用户选择。
  2. 动态换肤:支持任意配色,哪个地方用什么颜色完全由用户控制,例如直接给用户提供一个调色板,让他自己玩去。并且这种方式非常适合用于组件,因为作为组件提供方来说,无法预知组件使用方面对的需求,所以得提供支持完全自定义的方案,让其根据具体的需求来配色。

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
评论
请登录