Files
2026-10-09 17:32:14 +08:00

4.3 KiB
Raw Permalink Blame History

title, description
title description
Segmented 分段控制器 在一组互斥选项中切换,滑块跟随选中项移动

Segmented 分段控制器

分段控制器把 2-5 个互斥选项并排展示,用一个会滑动的滑块指示当前选项。它比 Tabs 轻量:切换的是同一区域的视图模式,不是内容面板。

何时使用

  • 视图模式切换:列表 / 看板 / 时间线;
  • 粒度切换:日 / 周 / 月;
  • 表单里的少量选项(2-5 项)时,比 Select 更快、比 Radio 更紧凑;
  • 选项超过 5 个、或需要多选时,请改用 Select / Checkbox。

基础用法

options 可以直接传原始值数组,选中值通过 v-model 双向绑定(支持字符串、数字、布尔)。

对象选项

选项写成对象可以自定义显示文字、加图标、单独禁用某一项。

圆角形状

纵向排列

vertical 时滑块上下移动,适合做侧边栏的视图切换。

撑满宽度

block 让各项等分父容器宽度(纵向时为高度),常用于移动端或表单顶部。

自定义每项内容

#label 插槽作用域为 { option, index, checked }:option 是原始选项对象,checked 表示该项是否选中。

非受控用法

不传 modelValue 时组件内部维护选中值(默认不选中),通过 change 把结果抛给业务。

API

Props

名称 类型 默认值 说明
modelValue string | number | boolean — 双向绑定的选中值。不传即非受控
options Array<SegmentedOptionInput> [] 选项数据源,元素可以是原始值或 { label, value, disabled, icon }
shape 'default' | 'round' 'default' 圆角形状。round 为全圆角胶囊
vertical boolean false 纵向排列,滑块上下移动
block boolean false 撑满父容器并等分各项
disabled boolean false 禁用整组
name string 自动生成 原生 radio 组名。不传时用 useId 生成,避免多组互斥冲突

Events

名称 参数 说明
update:modelValue (value: string | number | boolean) 选中项变化时触发(受控与非受控都会触发)
change (value: string | number | boolean) 同上,便于只监听变化

Slots

名称 参数 说明
label { option: SegmentedOptionInput, index: number, checked: boolean } 自定义每项内容;不传时渲染 icon + label

类型定义

export type SegmentedValue = string | number | boolean

export interface SegmentedOption {
  label?: string
  value: SegmentedValue
  disabled?: boolean
  icon?: Component | VNode
}

export type SegmentedOptionInput = SegmentedValue | SegmentedOption
export type SegmentedShape = 'default' | 'round'

样式变量

变量 默认值 说明
--g3-segmented-padding 2px 轨道内边距
--g3-radius 6px 轨道圆角(round 时为全圆角)
--g3-fill rgba(0,0,0,.04) 轨道底色
--g3-bg-container #fff 滑块底色
--g3-shadow 0 2px 8px rgba(0,0,0,.15) 滑块投影

实现说明

  • 底层是原生 radio 组(input[type=radio] + <label>),因此键盘方向键切换、屏幕阅读器分组语义都由浏览器原生提供;
  • 滑块的位移与尺寸通过 getBoundingClientRect 测量并写入 CSS 变量,容器尺寸变化时用 ResizeObserver 重算,所以字体缩放、文案长度变化都能跟上;
  • 首次渲染时滑块先隐藏(thumbVisible),测量完成后再淡入,避免从 (0,0) 位置滑过来的闪动;
  • 选项里的图标会经过 toRaw 处理:options 常由 ref 提供,直接使用会被深层响应式包装,触发 Vue 的「组件被响应式化」告警;
  • 与 Tabs 的区别:Segmented 没有面板,只负责"选择";Tabs 负责"选择 + 内容区 + 懒渲染"。