一、用户故事
我们组有多个团队多个项目,遵循同一规范,虽然有很多高度重叠的模块,但是各自为战,重复造了很多一个的轮子。所以这时候就是业务组件库来解决这一问题。
我们组遵循的设计规范理论上是要依托于另外一个部门的UI组件库。这个UI组件库基于element ui之上,进行了主题的修改和样式的扩展的,实现的方式是直接修改的源码。
而问题就出在这里。我们组的项目都升级为vue3版本了。所以公共部分的UI组件库自然无法使用。
在沟通过后,知晓他们升级的vue3的版本是elment plus。且实在等不及它们版本的升级,所以我们决定自己弄一套主题临时过渡。
二、需求分析
在确定了我们的需求之后,从需求中拆解出重点。
- 主题包括主题色和样式的扩展
- 临时
基于以上两点,我们可以得出下面的分析。我有如下三种实现方案:
直接对样式进行覆盖
比如说button的样式是el-button
来控制的。只要知道他们的类名,就可以直接通过类名来进行样式的覆盖。但是这样会有一个问题,我们的前端使用的是qiankun框架。qiankun字段的样式隔离模式就是一个坑。所以我们都是通过命名空间来隔离的。
如果我们直接对样式进行覆盖的话,el
这个前缀如何让用户传进来是一个问题。除此之外,怎么才能能什么classname控制什么样式呢?阅读源码还是打开element plus官网看着控制台?
这样的方式费力费劲。
弃之。
直接将element plus上面的 theme-chelk 项目拷贝下来,对源码进行修改
这个方案实现的起来比较简单,但是是在我做完之后才体会到这方案的好。一开始还是太年轻了。
当时排除的原因就是觉得这样要弄清楚element plus主题项目的代码,才可以下手,毕竟是临时用的,觉得会花很多的时间。
没想到的是,我后面选择的这个方案也需要看完源码。。。
很遗憾的弃之。
使用 scss 的特性对element的样式进行覆写
这个方案的在我草草看了官网就定下来的,感觉很简单。唯一的需要的就是对 scss 比较全面的了解。也是因为这个原因,实现的时候掉入了不少的坑。
三、需求实现
遗憾的选择了第三种方案,那么就要解决相应的问题。由于我们的业务组件库和业务项目都是依托于element plus的,所以业务组件库是不将element plus
打包进项目当中的。
综上所述,我们需要做如下的工作:
3.1 获取自定义命名空间
由于我们的项目是通过自定义命名空间来解决样式隔离的问题的。所以说我们需要一个入口,让用户在使用我们的业务组件库的时候传进他们的自定义命名。
一开始我走了弯路,在查找js如何将变量传入scss当中。搜索了半天没有任何结果。就在想要通过插件来实现的时候。突然发现了一个很简单的方法:
用户在使用我们的主题的时候,需要单独创建一个scss
文件:
@forward '@bbb/design-theme/src/index.scss' with (
$bbbNamespace: 'yarn'
);
也就是通过scss覆写的方式将@bbbNamespace这个变量传进来。然后我们在@bbb/design-theme/src/index.scss
中接受:
$bbbNamespace: 'el' !default;
@forward 'element-plus/theme-chalk/src/mixins/config.scss' with (
$namespace: $bbbNamespace
);
就这。就这。
我想了一天。源于一直以来对于scss这种的排斥,我从来没有去学过。用到的时候才知道痛。
3.2 主题色的改变
官网已经很明确了。主题 | Element Plus (gitee.io)
使用scss的minxin和@forward搭配来对样式进行重写。
前提是我们需要知道什么是主题色。我们可以通过控制台的Elements的Styles来直接查看:
随后直接:root {}
覆盖即可。
3.3 组件样式的扩展
我们以扩展button
的类型的为例子。默认的button
的size
类型有large | mudium | default
三种类型。现在我们想要给它添加一个bbb
类型。
打开 element-plus/theme-chalk/src/button.scss 文件,可以看到控制button的size如下:
知道了控制button的size值是由@button-padding-vertical
、@button-padding-horizontal
、@button-border-width
、@button-font-vsize
、@button-border-radius
这五个变量来定义的。
打开element-plus/theme-chalk/src/common/var.scss 文件,可以看到这五个变量的定义,我们就需要再index.scss中覆写他们,如下:
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
$button-padding-horizontal: (
'large': 24px,
'bbb': 16px
),
$button-padding-vertical: (
'large': 10px,
'bbb': 6px
),
$button-font-size: (
'bbb': 12px
)
)
但是我们没有办法直接给上图中的@each @size in (large, small)。。。
添加一个bbb。也就是说这个时候直接变量,而没有对应的大小class name。
对于这个问题,我的解决方法就比较直接,直接在index.scss中写一个出来,如下:
@use 'element-plus/theme-chalk/src/common/var' as *;
.#{$gasNamespace}-button--mini {
padding: (map.get($button-padding-vertical, 'mini') - $button-border-width)
(map.get($button-padding-horizontal, 'mini') - $button-border-width);
font-size: map.get($button-font-size, 'mini');
border-radius: map.get($button-padding-vertical, 'small');
&.is-round {
padding: (map.get($button-padding-vertical, 'mini') - $button-border-width)
(map.get($button-padding-horizontal, 'mini') - $button-border-width);
}
}
值得注意的是,上面我们只是对于element-plus/theme-chalk/src/common/var.scss
的重写。所以我们在下面想要使用它的话,还需要单独的引用才可以。
至此,给button组件的size属性添加一个bbb
类型的方式就实现了。
如果有更好的方法,求求大家发给我。
“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 21 天,点击查看活动详情”