button 组件开发
button 按钮咱们就对着 elment-ui 的 button 种类和样式来做,不一定特别全面,但是基本够用了,如果需要的话,可以自己加一些样式。
写一下基础样式
创建文件,theme/src/index.scss,接着创建 theme/src/x-button.scss。在 x-button.scss 中写一下基础样式:
.x-button {
display: inline-flex;
align-items: center;
justify-content: center;
height: 32px;
min-width: 80px;
padding: 0 16px;
background-color: #fff;
border-radius: 12px;
border: 1px solid #e6e6e6;
box-sizing: border-box;
line-height: 1;
color: #4e5159;
text-align: center;
font-size: 14px;
white-space: nowrap;
transition: 0.3s;
cursor: pointer;
user-select: none;
vertical-align: middle;
// 去掉按钮点击的默认样式和边框线
&:focus {
outline: none;
border: none;
}
span {
line-height: 1;
display: inline-flex;
align-items: center;
}
}
以上都是一些简单的 css 样式这里我就不做介绍了。在 index.scss 中引入一下这个样式:
@use "./x-button.scss";
在 example 中的 main.js 中引入一下这个样式:
import "@ui-library/theme/src/index.scss";
这样就可以看到 button 组件样式发生了改变
添加按钮类型
在 XButton 里面的 index.vue 中需要加一下 modifier,然后根据不同的 modifier 来设置不同的样式。在 props 中接收传递来的类型。具体代码如下:
<script setup>
import { useNamespace } from "@ui-library/hooks";
defineOptions({
name: "XButton",
});
const props = defineProps({
type: {
type: String,
default: "default",
},
});
const ns = useNamespace("button");
</script>
<template>
<button :class="[ns.block(), ns.modifier(type)]">
<span>
<slot>button</slot>
</span>
</button>
</template>
以上代码中在:class 中添加了 ns.block()
和 ns.modifier(type)
,然后根据不同的 type 来设置不同的样式。
ns.block()
:这个就是我们之前在 x-button.scss 中定义的 .x-button 这个类名,就是我们最终要渲染的按钮。ns.modifier(type)
:这个最终生成的是 .x-button-default 这个类名,就是我们根据不同的 type 来设置不同的样式。如果传递的 type 是 danger,那么最终生成的就是 .x-button-danger 这个类名。
在 x-button.scss 添加不同类型的样式
.x-button {
// 省略其他样式
// 。。。。。。
// 添加不同类型样式
&-- {
&default {
border-color: #e3e5f1;
&:hover {
background-color: #6e96ff;
color: white;
border-color: #6e96ff;
}
}
&success {
background-color: #67c23a;
color: white;
border-color: #67c23a;
&:hover {
background-color: #a2d380;
color: white;
border-color: #a2d380;
}
}
&danger {
background-color: #f56c6c;
color: white;
border-color: #f56c6c;
&:hover {
background-color: #f78989;
color: white;
border-color: #f78989;
}
}
&warning {
background-color: #e6a23c;
color: white;
border-color: #e6a23c;
&:hover {
background-color: #ebb563;
color: white;
border-color: #ebb563;
}
}
&primary {
background-color: #409eff;
color: white;
border-color: #409eff;
&:hover {
background-color: #66b1ff;
color: white;
border-color: #66b1ff;
}
}
}
}
以上都是 css 基础语法我就不做介绍了,大家可以参考一下。
圆角按钮
:class="[ns.block(), ns.modifier(type), ns.is('round', round),]"
,这段代码中,ns.is('round', round)
,round 是一个布尔值,如果 round 为 true,那么就会添加 is-round。然后在 defineProps 中接收 round 这个参数,然后根据这个参数来设置不同的样式。具体代码如下:
<script setup>
import { useNamespace } from "@ui-library/hooks";
defineOptions({
name: "XButton",
});
const props = defineProps({
type: {
type: String,
default: "default",
},
round: {
type: Boolean,
default: false,
},
});
const ns = useNamespace("button");
</script>
<template>
<button :class="[ns.block(), ns.modifier(type), ns.is('round', round)]">
<span>
<slot>button</slot>
</span>
</button>
</template>
在 x-button.scss 添加圆角样式
.x-button {
// 省略其他样式
&.is-round {
border-radius: 100px;
}
}
禁用按钮
继续在 class 中添加代码ns.is('disabled', disabled),
然后在 props 里面增加 disabled 这个参数,然后根据这个参数来设置不同的样式。还要设置一下 botton 按钮的禁用属性。具体代码如下:
<script setup>
import { useNamespace } from "@ui-library/hooks";
defineOptions({
name: "XButton",
});
const props = defineProps({
type: {
type: String,
default: "default",
},
round: {
type: Boolean,
default: false,
},
disabled: {
type: Boolean,
default: false,
},
});
const ns = useNamespace("button");
</script>
<template>
<button
:disabled="disabled"
:class="[
ns.block(),
ns.modifier(type),
ns.is('round', round),
ns.is('disabled', disabled),
]"
>
<span>
<slot>button</slot>
</span>
</button>
</template>
在 x-button.scss 添加禁用样式
.x-button {
// 省略其他样式
// 添加禁用样式
&.is-disabled {
cursor: not-allowed;
opacity: 0.5;
&,
&:hover,
&:active,
&:focus {
border-color: #e3e5f1;
}
}
}
尺寸按钮
在 x-button.vue 中增加一个 size 属性,然后根据这个属性来设置不同的样式。具体代码如下:
<script setup>
import { useNamespace } from "@ui-library/hooks";
defineOptions({
name: "XButton",
});
const props = defineProps({
//省略其他代码....
// 添加 size 属性
size: {
type: String,
default: "",
},
});
const ns = useNamespace("button");
</script>
<template>
<button
:disabled="disabled"
:class="[
// 省略其他代码....
ns.modifier('size', size),
]"
>
<span>
<slot>button</slot>
</span>
</button>
</template>
以上代码唯一的区别就是 modifier 方法的参数,我们在第二个参数上添加了值
在 x-button.scss 添加不同尺寸样式
.x-button {
// 省略其他代码....
&-- {
// 省略其他代码....
&size {
&_ {
&small {
padding: 0 10px;
font-size: 12px;
height: 24px;
border-radius: 10px;
}
&large {
height: 40px;
font-size: 16px;
}
}
}
}
}
icon 按钮
这里我先用阿里 icon 图标库来做一个图标按钮,后面我回进一步封装 icon 组件。项目中如何使用阿里 icon 图标库我就不在这里赘述了相对简单大家可以自己去搜索一下,但是要注意的是 icon图标库是加在 example 项目里面的,不需要在组件库中添加。具体代码如下:
<script setup>
import { useNamespace } from "@ui-library/hooks";
defineOptions({
name: "XButton",
});
const props = defineProps({
//省略其他代码....
icon: {
type: String,
default: "",
},
});
const ns = useNamespace("button");
</script>
<template>
<button
:class="[
// 省略其他代码....
]"
>
<i v-if="icon" class="x-icon iconfont" :class="icon"></i>
<span v-if="$slots.default">
<slot>button</slot>
</span>
</button>
</template>
以上代码很好理解,如果 icon 不为空,那么就显示 icon 图标,并且 icon 图标的 class 为 x-icon iconfont,然后根据 icon 的值来显示对应的图标。在 span 中添加了v-if="$slots.default"
, 用来判断是否有默认插槽,如果有默认插槽就显示默认插槽的内容,如果没有默认插槽就显示 icon 图标。
添加 icon 图标样式
和 x-button.scss 同级创建一个 x-icon.scss,增加如下代码
// span标签左边距离icon标签的距离
.x-icon + span {
margin-left: 5px;
}
在 index.css 中引入 x-icon.scss
@import "./x-icon.scss";
加载中按钮
加载中按钮和禁用按钮的效果一样,唯一的区别就是多了一个 在装圈圈的动画。具体代码如下。这个按钮的作用就是防止用户重复点击按钮,防止多次提交数据。
<script setup>
import { useNamespace } from "@ui-library/hooks";
defineOptions({
name: "XButton",
});
const props = defineProps({
//省略其他代码....
loading: {
type: Boolean,
default: false,
},
disabled: {
type: Boolean,
default: false,
},
});
const ns = useNamespace("button");
</script>
<template>
<button
:disabled="disabled || loading"
:class="[
// 省略其他代码....
ns.is('loading', loading),
]"
>
<template v-if="loading">
<i
class="a-icon iconfont icon-jiazai"
:class="[ns.is('loading-transition', loading)]"
></i>
</template>
<i v-else-if="icon" class="x-icon iconfont" :class="icon"></i>
<span v-if="$slots.default">
<slot>button</slot>
</span>
</button>
</template>
增加了 disabled 和 loading 如果有一个是 true 就禁用按钮,并且显示加载中的动画。i 标签中增加了:class="[ns.is('loading-transition', loading)]"
,这个是加载动画的动画效果。
添加加载中动画样式
.x-button {
// 省略其他代码....
&.is-disabled,
&.is-loading {
cursor: not-allowed;
opacity: 0.5;
&,
&:hover,
&:active,
&:focus {
border-color: #e3e5f1;
}
}
}
以上代码中添加了.is-loading
这个和.is-disabled
一样的样式
在增加 theme/src/loading.scss 文件并中添加如下代码:
.is-loading-transition {
animation: name duration timing-function delay iteration-count direction
fill-mode;
}
@keyframes name {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}