这是我参与8月更文挑战的第14天,活动详情查看:8月更文挑战
今天这篇文章来写写如何用vue2.x来从0开始搭建一个UI组件库,感兴趣的童鞋请往下冲~~
系统:win10
手脚架:vue-cli@4.5.12
一、创建项目
vue create zhbx-ui
选择Manually select features,手动选择需要的插件:
- Babel
- CSS Pre-processors
- Linter / Formatter
- Unit Testing
然后选择vue版本,这里选择vue2.x:
选择sass:
选择eslint风格:
选择测试库:选择ESLint + Prettier,
选择配置文件生成位置:
项目创建成功后删除App.vue文件中关于Helloworld组件的代码,删除components和assets文件夹中的内容。
下面开始封装组件啦~~
二、封装button组件
重点:
-
对于自定义的内容使用slot
-
查询slot是否有自定义内容用$slots
-
获取有相似类名的类可用
[class*=j-icon-]
1.参数支持
| 参数名 | 参数类型 | 参数描述 | 默认值 |
|---|---|---|---|
| type | string | 按钮类型(primary/success/info/warning/danger) | primary |
| plain | boolean | 是否是朴素按钮 | false |
| round | boolean | 是否是圆角按钮 | false |
| circle | boolean | 是否是圆形按钮 | false |
| disabled | boolean | 是否是禁用按钮 | false |
| icon | string | 图标类名 | 无 |
1.1.获取按钮名称: 用户可以给按钮设置名称,所以我们需要使用插槽slot来获取按钮名称。
<div class="zh-button">
<span v-if="$slots.default">
<slot></slot>
</span>
</div>
1.2. 获取type属性 获取用户设置的属性可以用props,为了避免用户乱传数据,所以我们需要对属性进行校验,限制其只能为String类型。
props: {
type: {
type: String,
default: "primary",
},
},
将获取到的type属性设置为类名,对不同类名的按钮设置不同的颜色,即可在用户传入不同的type时返回不同颜色的按钮。
<div class="zh-button" :class="[`zh-button--${type}`]">
<span>
<slot></slot>
</span>
</div>
1.3. 获取plain、round、circle属性 这三个属性一样是通过props获取与校验,一样设置为类名,通过不同类名来展示不同状态。
<div class="zh-button" :class="[`zh-button--${type}`, {
'is-plain': plain,
'is-circle': circle,
'is-round': round
}]">
<span>
<slot></slot>
</span>
</div>
1.4. 设置disabled属性
disabled属性的获取与上面四个属性一样,都是通过props获取,设置为类名,通过不同类名来展示不同状态。
不过有一个重点是,disabled要真正的被设置到,所以我们还需要加上原生的disabled属性。
<div
class="zh-button"
:class="[
`zh-button--${type}`,
{
'is-plain': plain,
'is-circle': circle,
'is-round': round,
'is-disabled': disabled
}]"
:disabled="disabled"
>
<span v-if="$slots.default"><slot></slot></span>
</div>
1.5. 设置icon属性
- 从iconfont上下载所需要的图标,放到src/assets/font文件夹中。
- 将iconfont.css文件中的
.iconfont类名改为[class*="zh-icon-"],这样使用的时候就可以不用加上iconfont类名了。 - 先在全局(main.js)引入iconfont.css文件。
- Button组件中设置接收icon:
<div
class="zh-button"
:class="[
`zh-button--${type}`,
{
'is-plain': plain,
'is-circle': circle,
'is-round': round,
'is-disabled': disabled
}]"
:disabled="disabled"
>
<i v-if="icon" :class="icon"></i>
<span v-if="$slots.default"><slot></slot></span>
</div>
给所有icon后面的文字加上一个间距:
.zh-button [class*="zh-icon-"]+span {
margin-left: 5px;
}
2.事件支持
| 事件名 | 事件描述 |
|---|---|
| click | 点击事件 |
如果我们没有给button组件添加click事件支持的话,用户在设置click事件时是没有反应的。
所以我们应当给button添加click事件,使用$emit触发用户传入的click事件,返回事件对象e。
<template>
<div
class="zh-button"
:class="[
`zh-button--${type}`,
{
'is-plain': plain,
'is-circle': circle,
'is-round': round,
'is-disabled': disabled
}]"
:disabled="disabled"
@clcik="handleClick"
>
<i v-if="icon" :class="icon"></i>
<span v-if="$slots.default"><slot></slot></span>
</div>
</template>
<script>
export default {
name: "ZhButton",
props: {
type: {
type: String,
default: "default",
},
plain: {
type: Boolean,
default: false,
},
circle: {
type: Boolean,
default: false,
},
round: {
type: Boolean,
default: false,
},
icon: {
type: String,
default: ""
},
disabled: {
type: Boolean,
default: false
}
},
methods: {
handleClick(e) {
// 触发用户的click事件,返回事件对象e
this.$emit('click', e)
}
}
};
</script>