Skip to content

UseElButton - 按钮

组件介绍

UseElButton 是基于 Element Plus 的el-button进行二次封装的通用按钮组件,旨在简化按钮的使用流程、统一交互逻辑、减少重复开发成本。该组件兼容el-button原生所有属性,同时内置防抖、二次确认等高频业务能力,仅需通过配置项即可完成绝大部分按钮场景的开发,无需重复编写防抖、弹窗确认等业务逻辑代码,大幅提升中后台系统中按钮的开发效率和可维护性。

核心亮点

  1. 防抖能力内置化:组件内置防抖配置项,通过 extConfig.debounce 可灵活配置防抖延迟时间、是否立即执行,无需手动封装防抖函数,一键实现按钮点击防抖,适配高频点击(如提交、查询)场景。
  2. 二次确认一键启用:通过 extConfig.confirm.data 显式配置即可开启二次确认能力,内置弹框文案、数据格式处理等逻辑,支持字符串 / 数字 / 对象 / 数组等多类型数据传入,无需重复编写 ElMessageBox 相关代码。
  3. 原生属性全兼容:完全继承 el-button 的所有原生属性(如 type、size 等),仅新增扩展配置项,无需担心原生能力缺失,同时统一按钮基础样式和交互逻辑。
  4. 数据格式自动处理:针对二次确认场景,组件自动处理对象 / 数组类型数据的主键提取、数组 / 字符串转换、字段名追加 s 等格式转换,无需手动编写数据处理逻辑,适配不同后端接口参数要求。
  5. 事件逻辑智能兼容:自动检测外部是否绑定原生 @click 事件,若绑定则优先触发外部逻辑,未绑定则执行内置防抖 / 二次确认逻辑,兼顾自定义扩展与内置能力的灵活切换。

解决痛点

1.按钮防抖逻辑重复开发

  • 痛点:中后台系统中提交、查询类按钮需频繁实现防抖逻辑,每个按钮都要手动引入防抖函数、配置延迟时间,不同页面防抖规则不统一,开发效率低且易遗漏。
  • 解决方案:组件内置防抖配置项 extConfig.debounce,通过 delay(防抖时间)、immediate(是否立即执行)即可统一配置防抖规则,无需手动封装防抖函数,全局防抖逻辑可统一维护。
  1. 二次确认弹框代码冗余
  • 痛点:删除、提交等高危操作按钮需添加二次确认弹框,每个按钮都要编写 ElMessageBox.confirm 逻辑,弹框标题、内容、数据处理逻辑分散在各页面,代码冗余且风格不统一。
  • 解决方案:组件通过 extConfig.confirm 配置项一键开启二次确认,内置弹框标题、内容、数据格式处理逻辑,仅需配置 data(确认数据)、title(弹框标题)、content(弹框内容)即可,减少 80% 以上的二次确认重复代码。
  1. 二次确认数据格式处理复杂
  • 痛点:二次确认场景中,需手动提取对象 / 数组的主键、转换数组为逗号分隔字符串、处理字段名复数(如 id 转 ids),不同开发者处理方式不同,易出现数据格式错误。
  • 解决方案:组件内置数据格式自动处理逻辑,通过 dataKey(主键名)、toArray(是否转数组)、appendS(是否追加 s)配置项,自动完成主键提取、格式转换、字段名处理,无需手动编写数据处理代码,数据格式规则全局统一。
  1. 原生 click 事件与内置逻辑冲突
  • 痛点:自定义按钮点击逻辑时,原生 @click 事件与组件内置防抖 / 二次确认逻辑易冲突,需手动判断触发时机,增加开发复杂度。
  • 解决方案:组件自动检测外部是否绑定 @click 事件,若绑定则仅触发外部逻辑,未绑定则执行内置防抖 / 二次确认逻辑,兼顾自定义扩展与内置能力,无需手动处理事件冲突。
  1. 全局按钮样式 / 交互不一致
  • 痛点:中后台系统多个页面的按钮,因无统一封装,样式污染、焦点状态异常等问题频发,且防抖、二次确认等交互逻辑分散,用户体验不一致。
  • 解决方案:组件内置统一的样式兼容逻辑(如解决 el-button 链接样式焦点污染问题),同时统一防抖、二次确认等交互逻辑,既保证全局样式 / 交互一致性,又支持通过原生 el-button 属性覆盖默认样式,满足个性化需求。
  1. 无统一的扩展配置规范
  • 痛点:按钮的防抖、二次确认等扩展能力无统一配置规范,不同页面配置方式各异,后期维护需逐个修改,维护成本高。
  • 解决方案:组件定义了清晰的 ExtConfig 接口,统一防抖、二次确认的配置项规范,所有扩展能力通过 extConfig 配置项集中管理,配置结构统一,后期调整扩展规则仅需修改组件核心逻辑,无需逐个页面适配。

使用案例

原生 + 防抖

二次确认

Types

js
import type { ExtractPropTypes } from 'vue'
import componentProps from './props'

/**
 * extConfig接口
 */
export interface ExtConfig {
  /**
   * 防抖配置项
   */
  debounce: {
    // 防抖时间
    delay: number
    // 是否立即开启防抖
    immediate: boolean
  }
  /**
   * 二次确认配置项
   */
  confirm: {
    // 二次确认数据 显式设置则开启二次确认,可为String、Number、Object、Array,无需传递数据则设置为null即可
    data?: string | number | unknown
    // 二次确认类型 同ElButton类型
    type: string
    // 二次确认数据主键key 对象或对象数组需要
    dataKey: string
    // 是否将以逗号分隔的字符串转换为数组 如:'1,2' => [1,2]
    toArray: boolean
    // 是否追加s到dataKey后面 如id => ids
    appendS: boolean
    // 二次确认弹框标题
    title: string
    // 二次确认弹框内容
    content: string
  }
}

/**
 * props类型
 */
export type Props = ExtractPropTypes<typeof componentProps>

/**
 * emits接口
 */
export interface Emits {
  //  点击事件 默认带防抖
  (e: 'onClick', value?: string | number | Record<string, unknown>): void
}

ComponentProps

js
import type { PropType } from 'vue'
import type { ExtConfig } from './types'

/**
 * 组件props
 */
export default {
  /**
   * 按钮文本 必传
   */
  btnText: {
    type: String,
    required: true
  },
  /**
   * 按钮类型 同ElButton类型,默认为primary
   */
  type: {
    type: String,
    default: 'primary',
    validator: (val: string) =>
      [
        '',
        'default',
        'primary',
        'success',
        'warning',
        'danger',
        'info'
      ].includes(val)
  },
  /**
   * 扩展配置 如【防抖/二次确认】等
   */
  extConfig: {
    type: Object as PropType<ExtConfig>,
    default: () => ({})
  }
}

DefaultExtConfig

js
import type { ExtConfig } from './types'

/**
 * 默认扩展配置
 */
export default {
  /**
   * 防抖配置项 仅作用于@onClick事件,无需防抖则设置delay为0或使用@click事件即可。
   * delay:防抖时间 默认500ms
   * immediate:是否立即开启防抖 默认否
   */
  debounce: { delay: 500, immediate: false },
  /**
   * 二次确认配置项
   * data:二次确认数据 显式设置则开启二次确认,可为String、Number、Object、Array,无需传递数据则设置为null即可
   * type:二次确认类型 默认danger,同ElButton类型
   * dataKey:二次确认数据主键key 默认id,对象或对象数组需要
   * toArray:是否将以逗号分隔的字符串转换为数组 如:'1,2' => [1,2]
   * appendS: 是否追加s到dataKey后面 如id => ids
   * title:二次确认弹框标题
   * content:二次确认弹框内容
   */
  confirm: {
    type: 'danger',
    dataKey: 'id',
    toArray: false,
    appendS: false,
    title: '删除提示',
    content: '确定将选择数据删除?'
  }
} satisfies ExtConfig

Props && Emits

js
const props = defineProps(componentProps)

const emits = defineEmits<Emits>()

基于 MIT 许可发布