1.button组件结构
typings/vue-shim.ts 定义组件大小状态
declare type ComponentSize = 'large' | 'medium' | 'small' | 'mini'
<template>
<button
:class="classs"
@click="handleClick"
:disabled="disabled"
>
<i v-if="loading" class="z-icon-loading"></i>
<i v-if="icon && !loading" :class="icon"></i>
<span v-if="$slots.default"><slot></slot></span>
</button>
</template>
<script lang="ts">
import { defineComponent, PropType, computed } from "vue";
export default defineComponent({
name: "ZButton",
props: {
type: {
type: String as PropType<
"primary" | "success" | "warning" | "danger" | "info" | "default"
>,
default: "primary",
validator: (val: string) => {
return [
"default",
"primary",
"success",
"warning",
"danger",
"info",
].includes(val);
},
},
size: {
type: String as PropType<ComponentSize>,
},
icon: {
type: String,
default: "",
},
loading: Boolean,
disabled: Boolean,
round: Boolean,
},
emits: ["click"],
setup(props, ctx) {
const classs = computed(() => [
"z-button",
"z-button--" + props.type,
props.size ? "z-button--" + props.size : "",
{
"is-disabled": props.disabled, // 状态全部以 is-开头
"is-loading": props.loading,
"is-round": props.round,
},
]);
const handleClick = (e) => {
ctx.emit("click", e);
};
return {
classs,
handleClick,
};
},
});
</script>
#2.button样式处理
@include b(button) {
// BEM规范
display: inline-block;
cursor: pointer;
outline: none;
border: #fafafa;
border-radius: 5px;
user-select: none;
min-height: 40px;
line-height: 1;
vertical-align: middle;
& [class*="#{$namespace}-icon-"] { // 处理icon 和文字间距
&+span {
margin-left: 5px;
}
}
@include when(disabled) { // 针对不同类型处理
&,
&:hover,
&:focus {
cursor: not-allowed
}
}
@include when(round) {
border-radius: 20px;
padding: 12px 23px;
}
@include when(loading) {
pointer-events: none;
}
@include m(primary) { //渲染不同类型的button
@include button-variant($--color-white, $--color-primary, $--color-primary)
}
@include m(success) {
@include button-variant($--color-white, $--color-success, $--color-success)
}
@include m(warning) {
@include button-variant($--color-white, $--color-warning, $--color-warning)
}
@include m(danger) {
@include button-variant($--color-white, $--color-danger, $--color-danger)
}
@include m(info) {
@include button-variant($--color-white, $--color-info, $--color-info)
}
}
提供scss的辅助方法,方便后续使用
@mixin button-variant($color, $background-color, $border-color) {
color: $color;
background: $background-color;
border-color: $border-color;
}
#3.Button组件试用
<template>
<div>
<z-button :loading="buttonLoading" @click="buttonClick">珠峰架构</z-button>
<z-icon name="loading"></z-icon>
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, ref } from "vue";
function useButton(){
const buttonLoading = ref(true);
onMounted(()=>{
setTimeout(() => {
buttonLoading.value = false;
}, 2000);
});
const buttonClick = () =>{
alert('点击按钮')
}
return {
buttonLoading,
buttonClick
}
}
export default defineComponent({
setup() {
return {
...useButton()
}
},
});
</script>
#Button-group组件
packages/button-group/index.ts
import { App } from 'vue'
import ButtonGroup from '../button/src/button-group.vue'
ButtonGroup.install = (app: App): void => {
app.component(ButtonGroup.name, ButtonGroup)
}
type IWithInstall<T> = T & { install(app: App): void; }
const _ButtonGroup:IWithInstall<typeof ButtonGroup> = ButtonGroup
export default _ButtonGroup
@include b(button-group) {
// BEM规范
&>.#{$namespace}-button {
&:first-child {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
&:last-child {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
}
}
<z-button-group>
<z-button type="primary" icon="z-icon-arrow-left-bold">上一页</z-button>
<z-button type="primary" >下一页<i class="z-icon-arrow-right-bold"></i></z-button>
</z-button-group>