如何在Vue.js中不依赖Vuetify实现类Vuetify按钮的自定义可复用属性
Vue3 + Tailwind CSS 自定义可复用按钮组件实现
核心实现思路
- 通过props定义所有可配置属性,布尔属性默认值设为false,直接传属性名即可生效
- 预定义不同属性对应的Tailwind工具类映射,避免动态拼接类名导致Tailwind无法识别
- 用computed动态组合所有样式类,优先级按需调整
完整组件代码(BaseButton.vue)
模板部分
<template> <button :type="type" :disabled="disabled" :class="btnClasses" > <slot /> </button> </template>
逻辑部分
<script> import { defineComponent, computed } from 'vue' export default defineComponent({ props: { // 原生按钮type属性 type: { type: String, default: 'button' }, // 按钮颜色主题:primary/danger/success/warning color: { type: String, default: 'primary' }, // 小尺寸按钮 small: { type: Boolean, default: false }, // 圆形图标按钮 fab: { type: Boolean, default: false }, // 深色适配样式 dark: { type: Boolean, default: false }, // 禁用状态 disabled: { type: Boolean, default: false } }, setup(props) { // 颜色样式映射,所有类名完整声明,避免Tailwind扫描丢失 const colorMap = { primary: { base: 'bg-blue-500 border-blue-500 text-white', hover: 'hover:bg-blue-600 hover:border-blue-600', active: 'active:bg-blue-700 active:border-blue-700', focus: 'focus:border-blue-700 focus:ring-blue-300' }, danger: { base: 'bg-red-500 border-red-500 text-white', hover: 'hover:bg-red-600 hover:border-red-600', active: 'active:bg-red-700 active:border-red-700', focus: 'focus:border-red-700 focus:ring-red-300' }, success: { base: 'bg-green-500 border-green-500 text-white', hover: 'hover:bg-green-600 hover:border-green-600', active: 'active:bg-green-700 active:border-green-700', focus: 'focus:border-green-700 focus:ring-green-300' }, warning: { base: 'bg-yellow-500 border-yellow-500 text-white', hover: 'hover:bg-yellow-600 hover:border-yellow-600', active: 'active:bg-yellow-700 active:border-yellow-700', focus: 'focus:border-yellow-700 focus:ring-yellow-300' } } const btnClasses = computed(() => { const classList = [ // 基础通用样式 'inline-flex items-center justify-center border border-transparent font-semibold uppercase tracking-widest focus:outline-none focus:ring transition ease-in-out duration-150', // 颜色样式 colorMap[props.color]?.base || colorMap.primary.base, colorMap[props.color]?.hover || colorMap.primary.hover, colorMap[props.color]?.active || colorMap.primary.active, colorMap[props.color]?.focus || colorMap.primary.focus, // 禁用样式 props.disabled ? 'opacity-25 cursor-not-allowed' : '' ] // fab圆形按钮样式 if (props.fab) { classList.push('rounded-full p-0 w-10 h-10') if (props.small) { classList.push('w-8 h-8 text-xs') } return classList } // 普通按钮尺寸样式 if (props.small) { classList.push('px-3 py-1 text-xs rounded-md') } else { classList.push('px-4 py-2 text-sm rounded-md') } // dark模式适配 if (props.dark) { classList.push('text-gray-100 border-opacity-20') } return classList }) return { btnClasses } } }) </script>
组件使用示例
用法和Vuetify的v-btn完全一致:
<!-- 圆形小尺寸主色按钮 --> <BaseButton fab small color="primary" class="mx-2"> <svg width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <!-- 自定义SVG图标内容 --> </svg> </BaseButton> <!-- 危险状态禁用按钮 --> <BaseButton color="danger" disabled>删除</BaseButton> <!-- 深色适配普通按钮 --> <BaseButton color="primary" dark>确认</BaseButton> <!-- 小尺寸成功按钮 --> <BaseButton color="success" small>提交</BaseButton>
内容的提问来源于stack exchange,提问作者Ruturaj Vaidya
相关产品推荐
相关产品推荐

