vue3+ts封装一个button组件(多样式动态class优化、加载3秒后可点击)

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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值