Segmented 分段控件
胶囊式切换器。只管选中值,不管内容。
基础用法
vue
<script setup>
import { ref } from 'vue'
const options = [
{ label: '列表', value: 'list' },
{ label: '网格', value: 'grid' },
{ label: '表格', value: 'table' }
]
const view = ref('list')
</script>
<template>
<SrSegmented v-model="view" :options="options" />
</template>当前选中:list
与 Tabs 的分工
两者都是「多选一」,但职责完全不同:
SrTabs | SrSegmented | |
|---|---|---|
| 内容 | 内含内容面板 | 不管内容 |
| 数据来源 | 子组件自动收集 | options 数组 |
| 样式 | 下划线 / 卡片 | 胶囊 + 滑动指示器 |
| 典型场景 | 分区切换(各区块内容不同) | 视图模式切换、筛选条件 |
一句话:Tabs 自带内容,Segmented 只告诉你用户选了什么。 切换后要渲染什么,由宿主根据选中的值决定。
作为筛选条件
分段控件最常见的用法之一是配合列表筛选——它只提供值,过滤逻辑在宿主。
宿主拿到 list 后自行决定如何渲染
禁用项
选项级的 disabled。禁用项仍显示在控件里—— 直接过滤掉会改变控件的宽度,用户会觉得「选项怎么少了一个」。
vue
const options = [
{ label: '可点', value: 1 },
{ label: '禁用', value: 2, disabled: true }
]尺寸
vue
<SrSegmented size="sm" :options="options" />
<SrSegmented size="md" :options="options" />
<SrSegmented size="lg" :options="options" />占满一行
block 让控件撑满父容器宽度,各选项等分。
vue
<SrSegmented v-model="view" :options="options" block />整体禁用
vue
<SrSegmented disabled :options="options" />滑动指示器
选中背景是一个绝对定位的滑块,切换时通过 transform: translateX() 平滑移动,而不是让两个选项的背景色瞬间互换。
用 transform 而不是 left:前者由合成器处理,不触发重排, 在列表页这类滚动场景下不会有掉帧感。
Props
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue | string | number | — | 当前选中值 |
options | { label, value, disabled? }[] | [] | 选项列表 |
size | 'sm' | 'md' | 'lg' | 'md' | 尺寸 |
block | boolean | false | 是否占满一行 |
disabled | boolean | false | 是否整体禁用 |
事件
| 事件 | 参数 | 说明 |
|---|---|---|
update:modelValue | 选中值 | 选中项变化 |
change | 选中值 | 同上(语义化事件) |
无障碍
- 容器用
role="radiogroup",每个选项role="radio"并带aria-checked—— 语义上它就是「一组里选一个」,与单选按钮一致 - 键盘:← → 在选项间移动,Home / End 跳到首尾
- 禁用项带
aria-disabled,读屏软件会播报但不会跳过它们, 保持选项顺序的可预测性