一个进度条组件的故事
1 捏造组件
1.1、组件技术
接着上一篇文章,选择vue-cli、typeScript搭建项目骨架。选择如下:
TS规则依旧是TSLint,测试选择mocha + chai,项目搭建完成后,将不必要文件夹删除,具体可参照上一篇文章,其他不过多赘述。
1.2、造轮子
其实,最好的组件参照就是撸组件库源码。在此,以element-ui组件库为参照,详解基础组件构造。 一打开element-ui源码,没有接触过的可能会有一些蒙圈,因为element已经算是一个高度完善的组件库了,里面包含了翻译语言、组件库文档、组件测试等。目前我们可以只看packages文件夹下的progress文件夹。
参照element-ui官网,找到进度条组件下的Attributes。可以发现,组件所需设置的参数。我们以percentage为例。 在自己的packages文件夹下新建progress组件。先把进度条样子编写出来。可以看到进度条是由两个div叠加形成的,
<div class="dy-progress-bar">
<div
class="dy-progress-bar_outer"
:style="{ height: strokeWidth + 'px' }"
>
<div class="dy-progress-bar_inner" :style="barStyle"></div>
</div>
</div>
<style lang="scss">
.dy-progress-bar {
margin-right : -55px;
box-sizing : border-box;
padding-right : 50px;
width : 100%;
display : inline-block;
vertical-align: middle;
.dy-progress-bar_outer {
border-radius : 100px;
background-color: #dcdfe6;
overflow : hidden;
position : relative;
vertical-align : middle;
}
}
.dy-progress-bar_inner {
position : absolute;
left : 0;
top : 0;
height : 100%;
text-align : right;
border-radius: 100px;
line-height : 1;
white-space : nowrap;
transition : width .6s ease;
background : #409eff;
}
<style>
骨架搭好之后,设置组件接收percentage参数。那么Prop传参设置好,参数又怎么控制进度条的呢?
在此,可以看到内部div绑定了一个样式:style="barStyle"。我们可以使用计算属性来控制div的长短。
get barStyle() {
let styles: any = {};
styles.width = this.percentage + '%';
styles.background = this.getCurrentColor(this.percentage);
return styles;
}
内部div的宽度占外部div整个宽度的百分之几,就是内部div的长度。这样就可以通过percentage这个参数控制。
在此也可以控制进度条的背景色color,设置组件接收color参数。可以通过官网发现colr可以存在三种类型,那么需要在定义时将color设置为string | Function | colorArrary[]。colorArrary类型数组可以是自定义的数组类型,模仿element数组格式,将colorArrary内部设置成color与percentage。
interface colorArrary {
color: string;
percentage: number;
}
在barStyle中,设置背景色的函数为getCurrentColor。在函数中需要判断接收的color是何种类型,如果是Function类型的话可以直接返回函数,用户可以自己定义;如果是string类型直接返回color变量;如果是Arrary类型,需要做一些处理。处理函数如getLevelColor。getColorArrary将接收到的数组,将整个div长度除以数组长度划分成一份span,再将每个元素乘以一份span,这样数组就可以获取到相对应的长度占比。通过长度不同(percentage增减)显示不同的进度条颜色。
private getCurrentColor(per: number) {
if (typeof this.color === 'function') {
return this.color(per);
} else if (typeof this.color === 'string') {
return this.color;
} else {
return this.getLevelColor(per);
}
}
private getLevelColor(per: number) {
let colorArr: colorArrary[] = this.getColorArrary().sort(
(a: colorArrary, b: colorArrary) => a.percentage - b.percentage,
);
colorArr.forEach((_: colorArrary) => {
if (_.percentage > per) {
return _.color;
}
});
return colorArr[colorArr.length - 1].color;
}
private getColorArrary() {
let color: any = this.color;
let span = 100 / this.color.length;
return color.map((c: colorArrary, i: number) =>
typeof c === 'string' ? { color: c, progress: (i + 1) * span } : c,
);
}
像format、status参数参数,则是在进度条旁加上一个div。控制显示图标还是文字。content为计算属性,通过接收的format参数显示百分比或则自定义文字。
<div class="dy-progress_text">
<template v-if="!status">{{content}}</template>
<dy-icon v-else :icon="iconClass"></dy-icon>
</div>
如果传入format为数值,则content可以直接返回百分比;若format传入类型为函数,则可以通过percentage自定义文字显示。
get content() {
if (typeof this.format === 'function') {
return this.format(this.percentage) || '';
} else {
return `${this.percentage}%`;
}
}
进度条基本功能就介绍到这啦!
2 打包组件
2.1、打包
打包组件为什么我要在说明一下呢,就是因为在这踩了个大坑啊!!!
上一篇文章注册组件时,使用Vue.component(DyButton.name, DyButton);注册。当时打包后的文件使用的是commonjs文件作为引用的入口文件,在编写vuepress文档时,并没有多注意。因为commonjs在doc文档项目中是可以使用的(建议使用后缀名为umd.min.js的压缩文件)。
当我部署到GitHub上时,发现组件写的组件库完全失效,而且并没有报错。
当时找了很多,比如vuepress部署样式失效的问题,但是我的vuepress文档基本样式还是有效的,所有证明我的路径并没有问题。
之后怀疑vuepress引用dying-ui组件库无效,但是本地可以运行,此想法再次被推翻。
再然后,js重写dying-ui组件库,发现部署没有问题。慢慢找到根本原因:ts编写组件库,使用component.name在打包后组件名也会压缩。所以在vuepress打包后组件库也是会被打包的。因此组件的name属性无效。
解决方法:
在组件中使用static静态变量public static comName = 'DyProgress';,注册组件时使用component.comName即可。
2.2、引用入口文件
在写组件库部署失效时,一直以为是打包后入口文件有问题,因为设置main为./dist/dying-ui.umd.min.js在本地组件库运行失效。换为./dist/dying-ui.common.js本地运行就可以。
其实两者并没太大区别。umd文件是糅合了AMD和CommonJs两种规范。只是组件库使用min的话,dy-ui-doc文档项目引用的直接为组件库打包后的文件,在文档项目部署时就不需要再去压缩组件库。而直接使用umd或者commonjs文件的话,在需要引用组件库的项目打包时,需要将组件库一同压缩打包,会出现注册组件名压缩导致组件失效。
3 组件文档
组件文档我选择的时vuepress,根据官网教程,一步一步搭建文档项目即可。
像element官网中组件样式下展示组件代码,可以参照element源码中的element\examples\components\demo-block.vue文件。也可以使用dy-ui-doc项目中的模板,dy-ui-doc是将其去除在线运行功能的简化版。
组件库:dying-ui
文档:dy-ui-doc