十六、按钮组件

目录

一、解释

二、组件代码

三、使用组件


一、解释

一般之前就是用到按钮就直接<button>或者<el-button>啥的,每次都要重新写样式,功能啥的,这就直接封装成组件,复用就可以了

(1)可显示文字按钮

(2)可显示icon

(3)可开关的点击动画

(4)指定风格,大小

(5)风格不符时有提示

二、组件代码

src/libs/button/index.vue

javascript 复制代码
<script>
import { computed } from 'vue'
// 1.这个按扭风格可选项
const typeEnum = {
  primary: 'text-white bg-zinc-800 hover:bg-zinc-900 active:bg-zinc-800 dark:bg-zinc-900 dark:hover:bg-zinc-700 dark:active:bg-zinc-700',
  main: 'text-white bg-main hover:bg-hover-main active:bg-hover-main dark:bg-zinc-900 dark:hover:bg-zinc-700 dark:active:bg-zinc-700',
  info: 'text-zinc-800 bg-zinc-200 hover:bg-zinc-300 active:bg-zinc-200 dark:bg-zinc-700 dark:hover:bg-zinc-600 dark:text-zinc-300 dark:active:bg-zinc-700'
}

// 2.这个按扭大小可选项:区分文字与icon
const sizeEnum = {
  default: {
    button: 'w-8 h-4 text-base',
    icon: ''
  },
  'icon-default': {
    button: 'w-4 h-4',
    icon: 'w-1.5 h-1.5'
  },
  small: {
    button: 'w-7 h-3 text-base',
    icon: ''
  },
  'icon-small': {
    button: 'w-7 h-3 text-base',
    icon: ''
  }
}
</script>
<script setup>
const sizeKey = computed(() => {
  return props.icon ? 'icon-' + props.size : props.size
})

const props = defineProps({
  icon: String, // 图标
  iconColor: String, // 图标颜色
  iconClass: String, // 图标类名
  type: { // 按扭风格
    type: String,
    default: 'main',
    validator(val) {
      const keys = Object.keys(typeEnum)
      const result = keys.includes(val)
      if (!result) { // 如果样式不在可选项中,抛出错误
        throw new Error(`type 必须是 ${keys.join('、')} 中的一个`)
      }
    }
  },
  size: { // 按扭大小
    type: String,
    default: 'default',
    validator(val) {
      const keys = Object.keys(sizeEnum).filter((key) => !key.includes('icon'))
      const result = keys.includes(val)
      if (!result) { // 如果大小不在可选项中,抛出错误
        throw new Error(`size 必须是 ${keys.join('、')} 中的一个`)
      }
    }
  },
  isActiveAnim: { // 点击动画
    type: Boolean,
    default: true
  },
  loading: { // 加载状态
    type: Boolean,
    default: false
  }
})
</script>
<template>
  <button
    class="text-sm text-center rounded duration-150 flex justify-center items-center"
    :class="[
      typeEnum[type],
      sizeEnum[sizeKey].button,
      { 'active:scale-105': isActiveAnim }
    ]"
    @click.stop="onBtnClick"
  >
    <m-svg-icon
      v-if="loading"
      name="loading"
      class="w-2 h-2 animate-spin mr-1"
    ></m-svg-icon> <!--加载-->
    <m-svg-icon
      v-if="icon"
      :name="icon"
      class="m-auto"
      :class="sizeEnum[sizeKey].icon"
      :color="iconColor"
      :fillClass="iconClass"
    ></m-svg-icon> <!--icon图标-->
    <slot v-else /> <!--文字-->
  </button>
</template>

<style scoped lang="scss">
</style>

这里用到的bg-main是自定义颜色,在tailwind.config.js中定义

javascript 复制代码
/** @type {import('tailwindcss').Config} */
export default {
  content: [
    './index.html',
    './src/**/*.{vue,js,ts}'
  ],
  theme: {
    extend: {
        ...
      colors: {
        main: '#f44c58',
        'hover-main': '#f32836'
      }
    }
  },
  darkMode: 'class',
  plugins: []
}

三、使用组件

在search组件中使用

javascript 复制代码
      <!-- TODO: 搜索按钮(通用组件) -->
      <m-button
        class="absolute translate-y-[-50%] top-[50%] right-1 rounded-xl duration-500 opacity-0 group-hover:opacity-100"
        icon="search"
        iconColor="#ffffff"
        @click="onSearchHandlder"
      ></m-button>

至此,按钮组件完成

相关推荐
小码哥_常4 小时前
一套自己部署的 IM,客户端是同一份 Flutter
前端·后端
蜗牛攻城狮6 小时前
微前端四大方案选型对比与最佳实践:qiankun、micro-app、wujie、Module Federation
前端·微前端·qiankun·前端架构·micro-app·wujie
她说可以呀8 小时前
Vue插槽
前端·javascript·vue.js
qq_448011168 小时前
Vue + Jinja2两套模版与法冲突造成undefinedError
前端·javascript·vue.js
aixingpan8 小时前
aixingpan.cn API开发文档:前端查询夏令时和时区接口指南
前端·php
2601_958352909 小时前
23.5×19mm 换掉一整条音频链?|A-68 集成了什么:ADC / DAC / 24.576MHz 时钟 / AEC / 波束降噪,主控仅需 6 根线
前端·音视频·ai降噪·回声消除·语音模块
志尊宝9 小时前
AI原生前端开发(039):AI辅助的Nuxt 4全栈开发
前端·vue.js·ai-native
FRing0310 小时前
JavaScript入门到精通三十二(深拷贝、浅拷贝、递归函数)
开发语言·前端·javascript
excel10 小时前
双 Token 与前端使用 Crypto 公私钥鉴权换 Token,哪种方案更好?
前端·后端
外收内放10 小时前
Python基础语法练习题(73)
java·前端·python