TinyVue ButtonGroup 组件完全指南:让你的按钮组告别"各玩各的"

16 阅读7分钟

开篇:当按钮们决定"合体"

你有没有遇到过这种情况:页面上三个按钮一字排开,明明功能是互斥的——比如"日视图/周视图/月视图"——但它们长得像三个独立的按钮,用户选完"周视图","日视图"还亮着,仿佛在说"你可以同时选我哦"。

这就是传统按钮的痛点:它们天生是"独行侠",但现实场景中,你经常需要一组"非此即彼"的选项。

ButtonGroup(按钮组)就是来终结这种尴尬的。

它是 TinyVue 专门为"单选按钮组"场景设计的组件——不是那种圆圆的 radio,而是更直观的按钮式切换。点一个,上一个自动取消,像一群训练有素的士兵,只有一个能站出来。


1. 基础用法:三步打造一个按钮组

话不多说,先看代码:

<template>
  <tiny-button-group :data="groupData" v-model="checkedVal" />
  <p>当前选中值:{{ checkedVal }}</p>
</template>

<script setup>
import { ref } from 'vue'
import { TinyButtonGroup } from '@opentiny/vue'

const checkedVal = ref('Button1')
const groupData = [
  { text: 'Button1', value: 'Button1' },
  { text: 'Button2', value: 'Button2' },
  { text: 'Button3', value: 'Button3' }
]
</script>

三步到位:

  1. 定义数据源 data:每个按钮用 { text, value } 描述,text 是显示文字,value 是选中值。
  2. 绑定 v-model:双向绑定当前选中的值,点哪个切哪个。
  3. 坐等收获:页面上出现三个互斥的按钮,当前选中值实时显示。

这比手动写三个按钮再自己管理选中状态优雅多了——你不需要维护一个 activeIndex,不需要在 @click 里写一堆 if-else,ButtonGroup 全帮你搞定了。


2. 尺寸三兄弟:medium / small / mini

按钮组也讲究身材管理。通过 size 属性,一个属性就能让整组按钮集体"健身":

<tiny-button-group size="medium" :data="groupData" v-model="checkedVal" />
<tiny-button-group :data="groupData" v-model="checkedVal" />
<tiny-button-group size="small" :data="groupData" v-model="checkedVal" />
<tiny-button-group size="mini" :data="groupData" v-model="checkedVal" />

三种尺寸覆盖了从"桌面端舒适点击"到"移动端紧凑布局"的全场景需求。默认不写 size 等价于 medium——省事。

小贴士:不要试图给每个按钮单独设 size,ButtonGroup 的哲学是"步调一致",整个组一个尺寸,整齐才是美。


3. 禁用状态:让某些按钮"休假"

有时候某个选项暂时不可用——比如"导出PDF"功能还在开发中,但UI上又需要展示这个选项让用户知道即将支持。

ButtonGroup 支持两个粒度的禁用:

3.1 整体禁用

<tiny-button-group :data="groupData" disabled />

此时整个按钮组灰掉,全员罢工。适合表单提交中、数据加载中这类场景。

3.2 单个按钮禁用

const groupData = [
  { text: '日视图', value: 'day' },
  { text: '周视图', value: 'week' },
  { text: '月视图', value: 'month', disabled: true, tip: '即将上线' }
]

给数据项加个 disabled: true,单个按钮就灰掉了。再加个 tip 属性(v3.17.0+),鼠标悬浮时还能弹出提示,告诉用户为什么不能用——用户体验直接拉满。

这比你自己写 :disabled + 手写 tooltip 组合拳,少了至少三行模板代码。


4. 朴素按钮:低调的另一种选择

默认的按钮组是有填充色的,视觉上比较突出。但如果你需要"低调奢华"的风格——比如在表格工具栏、卡片底部区域——用 plain 属性一键切换:

<tiny-button-group :data="groupData" v-model="checkedVal" plain />

朴素模式下,按钮只保留边框和文字颜色,背景变为透明。选中态和默认态的区分依然清晰。


5. 数据字段映射:当你的后端不按套路出牌

这是个非常实用的功能。ButtonGroup 默认认 textvalue 这两个字段名,但现实中的接口数据可能是:

[
  { "label": "日视图", "id": "day" },
  { "label": "周视图", "id": "week" }
]

这时候不需要手动 map 转换数据,两个属性搞定:

<tiny-button-group
  :data="apiData"
  text-field="label"
  value-field="id"
  v-model="checkedVal"
/>

text-field 告诉组件从 label 字段取显示文字,value-field 告诉组件从 id 字段取选中值。省掉了循环转换的中间步骤,数据直接怼进去就行。


6. 显示更多:按钮太多?折叠它!

当一个按钮组里有七八个选项时,横向排开会很丑,甚至溢出容器。show-more 属性就是为这种情况准备的:

<tiny-button-group :data="longGroupData" :show-more="3" v-model="checkedVal" />

设置 show-more="3" 后,前面 3 个按钮正常显示,后面的统统收进"更多"按钮的下拉菜单里。点击"更多"展开,选完自动收起。

这个设计比你自己用 v-if + v-for + 下拉组件折腾方便太多了。


7. 默认插槽:当数据驱动不够用时

ButtonGroup 的数据驱动模式覆盖了 90% 的场景,但总有些时候你需要完全自定义——比如在按钮上加图标、或者按钮间的顺序和样式需要精细控制:

<tiny-button-group v-model="checkedVal">
  <tiny-button value="left">← 上一步</tiny-button>
  <tiny-button value="right">下一步 →</tiny-button>
</tiny-button-group>

使用默认插槽后,datatext-fieldvalue-fieldsize 等属性对插槽内的按钮不再生效。你获得了完全的控制权,但也需要自己处理样式和交互。

一句话总结:数据驱动走量,插槽走心。


8. 空数据插槽:优雅地处理"啥也没有"

数据为空时,ButtonGroup 默认显示"暂无数据"。如果你觉得太生硬,可以用 empty 插槽自定义:

<tiny-button-group :data="[]">
  <template #empty>
    <div style="color: #999;">🏃 按钮们跑路了,请稍后再来...</div>
  </template>
</tiny-button-group>

一个幽默的占位提示,比干巴巴的"暂无数据"友好多了。


9. 选块角标:按钮上的"小红点"

v3.17.0 版本新增的 sup 属性,让你能在按钮右上角加个小角标——就像微信消息的红点:

const groupData = [
  { text: '未读', value: 'unread', sup: { text: '99+' } },
  { text: '已读', value: 'read' },
  { text: '归档', value: 'archive', sup: { text: '新', class: 'custom-badge' } }
]

sup 可以配置:

  • text:角标文字
  • class:自定义样式类
  • slot:自定义插槽(用于更复杂的角标内容)
  • icon:传入图标组件

这在消息中心、任务列表等场景非常有用——用户一眼就能看到哪个分类有待处理内容。


10. 显示模式:从"独立单间"到"豪华套房"

display-mode 属性让按钮组有两种视觉风格:

<!-- 默认模式:按钮间有间距,各自独立 -->
<tiny-button-group :data="groupData" v-model="checkedVal" />

<!-- 合并模式:按钮无缝拼接,像一个整体 -->
<tiny-button-group :data="groupData" v-model="checkedVal" display-mode="merged" />
  • default(默认):按钮之间保持间距,每个按钮有独立的圆角。适合宽松布局。
  • merged(合并):按钮之间无缝贴合,首尾有圆角,中间是直角。形成"分段控制器"的视觉效果,类似 iOS 的 UISegmentedControl。

11. 多行按钮组:横向撑不下了,换行继续

按钮太多但不想用"显示更多"折叠?ButtonGroup 支持自动换行:

<tiny-button-group :data="manyGroupData" v-model="checkedVal" style="max-width: 400px;" />

当容器宽度不足以容纳所有按钮时,会自动换行显示。不需要额外的配置,CSS 自动处理。


12. Change 事件:时刻掌握"谁被翻了牌子"

<tiny-button-group :data="groupData" @change="handleChange" />

<script setup>
const handleChange = (value) => {
  console.log('切换到了:', value)
  // 这里可以做任何事:切换视图、请求数据、更新路由...
}
</script>

每次按钮切换都会触发 change 事件,回调参数就是新选中的 value。配合 v-model 使用,数据和事件的联动天衣无缝。


总结:ButtonGroup 该不该用?

场景是否推荐
互斥选项切换(日/周/月)✅ 强烈推荐
简单筛选(全部/已读/未读)✅ 强烈推荐
多个独立操作按钮❌ 用单独的 <tiny-button>
需要复杂自定义内容的选项✅ 用插槽模式
选项超过 8 个✅ 用 show-more 折叠

ButtonGroup 本质上是一个"单选按钮的按钮化呈现"——比 Radio 直观,比手写按钮组方便。它把"互斥选择"这个高频需求的开发成本降到了最低:

一行 data + 一行 v-model = 一个完美的按钮组。

下次你的页面上出现三个以上需要互斥的按钮时,别犹豫,ButtonGroup 就是你需要的答案。


OpenTiny NEXT 是一套企业智能前端开发解决方案,以生成式 UI 和 WebMCP 两大核心技术为基础,对现有传统的 TinyVue 组件库、TinyEngine 低代码引擎等产品进行智能化升级,构建出面向 Agent 应用的前端 NEXT-SDKs、AI Extension、TinyRobot智能助手、GenUI等新产品,实现AI理解用户意图自主完成任务,加速企业应用的智能化改造。 欢迎加入 OpenTiny 开源社区。添加微信小助手:opentiny-official 一起参与交流前端技术~
OpenTiny 官网:opentiny.design
TinyVue 代码仓库:https://https://github.com/opentiny/tiny-vue (欢迎star ⭐)