封装UI组件库系列第四篇·封装Button按钮组件
🌟前言
在前端开发中,大家可能已经用过各种各样的UI组件库了,现在市面上热门的有Element-ui、Ant Design等等,这些即插即用的组件库确实大大提升了开发效率,避免了很多的重复劳动,但这些组件库再怎么完善,又怎么能满足得了我们可爱的产品经理呢?所以工作中难免会需要开发公司内部的UI组件库,或者基于已有组件库进行二开。
【封装UI组件库系列】文章,将从0开始--》搭建项目--》封装八大经典功能组件--》打包组件库--》将组件库发布至npm--》使用自己封装的组件库。技术方面使用的是Vue3 + Vite + Sass 来完成一个模仿Element Plus的组件库。最终完成效果如下:
【封装UI组件库系列】建议从开篇开始阅读!!!https://blog.csdn.net/g_ing/category_12503768.html?spm=1001.2014.3001.5482
🌟封装Button组件
上一篇我们已经封装了第一个Icon组件,接下来我们就开始封装Button组件
1.分析封装组件所需支持的属性与事件
在开始敲代码前,我们需要先有个思路,要开发什么,需要什么功能,先定好,再动手:
支持的属性:
属性名 | 作用 | 类型 | 是否必须 | 默认值 |
---|---|---|---|---|
type | 主题颜色 | String | 否 | default |
size | 大小 | String | 否 | 无 |
plain | 是否朴素 | Boolean | 否 | false |
round | 是否圆角 | Boolean | 否 | false |
circle | 是否圆形 | Boolean | 否 | false |
disabled | 是否禁用 | Boolean | 否 | false |
loading | 是否加载中 | Boolean | 否 | false |
icon | 图标 | String | 否 | 无 |
支持的事件:
事件名 | 作用 |
---|---|
click | 点击事件 |
确定好要做的事情,就可以开干喽。
2.创建Button组件
创建组件Button.vue:
在main.js中引入注册:
在views/Button.vue中使用:
🌟封装功能属性
老规矩,新建src/components/Button/props.js 文件义属性:
type主题颜色
在props.js:
export default {
type: {
type: String,
default: 'default'
},
}
新建style/components/icon.scss
完善基本样式,其实这里很多用到的就是第二篇文章中定义的样式(具体代码文末):
接下来就是实现主题颜色:
前面文章也将过的,这里还是使用scss语法:
然后在组件中去判断有没有type,有的话就挂上对应样式类:
效果如下:
plain是否朴素
同理,定义样式:
定义props:
判断条件:
loading等待状态
这里需要用到上节课封装的Icon组件:
使用:
效果:
其他属性
讲过上面几种后其他的大差不差,直接上代码
/components/Button/Button.vue:
<template>
<button ref="_ref" class="visual-button" :class="{
[`visual-button--${type}`]: type,
[`visual-button--${size}`]: size,
'is-plain': plain,
'is-round': round,
'is-circle': circle,
'is-disabled': disabled || loading
}">
<Visual-Icon icon="spinner" spin v-if="loading" />
<Visual-Icon :icon="icon" v-if="icon" />
<span v-if="$slots.default">
<slot />
</span>
</button>
</template>
<script setup>
import propObj from './props'
defineOptions({
name: 'visual-Button'
})
defineProps(propObj)
</script>
<style lang="scss" scoped></style>
/components/Button/props.js:
export default {
type: {
type: String,
default: 'default'
},
plain: {
type: Boolean,
default: false
},
round: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
loading: {
type: Boolean,
default: false
},
icon: {
type: String
},
size: {
type: String
},
circle: {
type: Boolean,
default: false
}
}
styles/components/button.scss:
// 首先针对这个样式类里面,定义了一系列的样式变量
.visual-button {
--visual-button-font-weight: var(--visual-font-weight-primary);
--visual-button-border-color: var(--visual-border-color);
--visual-button-bg-color: var(--visual-fill-color-blank);
--visual-button-text-color: var(--visual-text-color-regular);
--visual-button-disabled-text-color: var(--visual-disabled-text-color);
--visual-button-disabled-bg-color: var(--visual-fill-color-blank);
--visual-button-disabled-border-color: var(--visual-border-color-light);
--visual-button-hover-text-color: var(--visual-color-primary);
--visual-button-hover-bg-color: var(--visual-color-primary-light-9);
--visual-button-hover-border-color: var(--visual-color-primary-light-7);
--visual-button-active-text-color: var(--visual-button-hover-text-color);
--visual-button-active-border-color: var(--visual-color-primary);
--visual-button-active-bg-color: var(--visual-button-hover-bg-color);
--visual-button-outline-color: var(--visual-color-primary-light-5);
--visual-button-active-color: var(--visual-text-color-primary);
}
.visual-button {
// 接下来再来书写基本的样式
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
height: 40px;
background-color: var(--visual-button-bg-color);
border: var(--visual-border);
border-color: var(--visual-button-border-color);
color: var(--visual-button-text-color);
appearance: none;
text-align: center;
box-sizing: border-box;
outline: none;
margin: 0;
transition: 0.1s;
font-weight: var(--visual-button-font-weight);
user-select: none;
vertical-align: middle;
padding: 12px 20px;
font-size: var(--visual-font-size-base);
border-radius: var(--visual-border-radius-base);
&:hover,
&:focus {
color: var(--visual-button-hover-text-color);
border-color: var(--visual-button-hover-border-color);
background-color: var(--visual-button-hover-bg-color);
outline: none;
}
&:active {
color: var(--visual-button-active-text-color);
border-color: var(--visual-button-active-border-color);
background-color: var(--visual-button-active-bg-color);
outline: none;
}
&.is-round {
border-radius: var(--visual-border-radius-round);
}
&.is-circle {
width: 45px;
height: 45px;
border-radius: 50%;
padding: 12px;
display: flex;
justify-content: center;
align-items: center;
}
// 禁用相关的样式
&.is-disabled,
&.is-disabled:hover,
&.is-disabled:focus,
&[disabled],
&[disabled]:hover,
&[disabled]:focus {
color: var(--visual-button-disabled-text-color);
cursor: not-allowed;
background-image: none;
background-color: var(--visual-button-disabled-bg-color);
border-color: var(--visual-button-disabled-border-color);
}
[class*='visual-icon'] + span {
margin-left: 6px;
position: relative;
bottom: 2px;
}
}
@each $val in primary, success, warning, info, danger {
// 这是一种非常灵活的方式,通过挂上去一些类,改变 CSS 变量所对应的值
.visual-button--#{$val} {
--visual-button-text-color: var(--visual-color-white);
--visual-button-bg-color: var(--visual-color-#{$val});
--visual-button-border-color: var(--visual-color-#{$val});
--visual-button-outline-color: var(--visual-color-#{$val}-light-5);
--visual-button-active-color: var(--visual-color-#{$val}-dark-2);
--visual-button-hover-text-color: var(--visual-color-white);
--visual-button-hover-bg-color: var(--visual-color-#{$val}-light-3);
--visual-button-hover-border-color: var(--visual-color-#{$val}-light-3);
--visual-button-active-bg-color: var(--visual-color-#{$val}-dark-2);
--visual-button-active-border-color: var(--visual-color-#{$val}-dark-2);
--visual-button-disabled-text-color: var(--visual-color-white);
--visual-button-disabled-bg-color: var(--visual-color-#{$val}-light-5);
--visual-button-disabled-border-color: var(--visual-color-#{$val}-light-5);
}
// 如果挂了 is-plain 这个,那么同样是改变一些 CSS 变量的值
.visual-button--#{$val}.is-plain {
--visual-button-text-color: var(--visual-color-#{$val});
--visual-button-bg-color: var(--visual-color-#{$val}-light-9);
--visual-button-border-color: var(--visual-color-#{$val}-light-5);
--visual-button-hover-text-color: var(--visual-color-white);
--visual-button-hover-bg-color: var(--visual-color-#{$val});
--visual-button-hover-border-color: var(--visual-color-#{$val});
--visual-button-active-text-color: var(--visual-color-white);
}
}
// 针对 visual-button-large 以及 visual-button-small 书写相应的样式即可
.visual-button--large {
--visual-button-size: 50px;
height: var(--visual-button-size);
padding: 12px 19px;
font-size: var(--visual-font-size-base);
border-radius: var(--visual-border-radius-base);
}
.visual-button--small {
--visual-button-size: 24px;
height: var(--visual-button-size);
padding: 5px 11px;
font-size: 12px;
border-radius: calc(var(--visual-border-radius-base) - 1px);
}
🌟总结
【封装UI组件库系列】文章会持续更新,将带着大家从0开始--》搭建项目--》封装八大经典功能组件--》打包组件库--》将组件库发布至npm--》最后使用自己封装的组件库。如果文中出现有瑕疵的地方各位通过评论或者私信联系我,我们一起进步!该系列文章建议从第一篇开始看,系列专栏地址:从零开始封装UI组件库完整篇