☰
tdesign-miniprogram Segmented 分段控制器:从接入、受控值到源码级原理全解析
2026/10/15 15:50:45 网站建设 项目流程
  • 前端
  • UI组件
  • 小程序
  • 设计系统
  • 移动开发

【免费下载链接】tdesign-miniprogram

Wechat MiniProgram and Uniapp UI components lib for TDesign

项目地址:https://gitcode.com/gh_mirrors/tde/tdesign-miniprogram
点击查看免费下载

本文以 Segmented 分段控制器官方文档 为核心,结合组件源码、示例与测试,系统讲解 tdesign-miniprogram 中分段控制器的接入方式、数据化配置、禁用态、事件回调以及底层实现原理。读完本文,你将能在微信小程序中熟练配置t-segmented,理解其"滑块动画"的实现机制,并能通过 External Classes 与 CSS Variables 完成深度定制。

组件概览:面向单选的轻量控制器

Segmented 分段控制器用于展示多个选项并允许用户选择其中单个选项,是典型的单选项切换组件。根据 官方文档,该组件于1.14.0 版本上线,使用前需要留意项目所依赖的 tdesign-miniprogram 版本;渲染框架方面同时支持Skyline 与 WebView两种渲染方式,并且仓库中已提供 Skyline 渲染示例,可在 Skyline 页面中直接复用。

快速接入:全局与局部引入

分段控制器属于页面级组件,接入方式与其他 tdesign-miniprogram 组件一致,支持两种引入方式(详见 README 引入章节):

  • 全局引入:在小程序根目录app.json的usingComponents中注册,全项目可用;
  • 局部引入:在需要使用组件的页面或组件自身的index.json中注册。

配置示例如下:

{ "usingComponents": { "t-segmented": "tdesign-miniprogram/segmented/segmented" } }

接入后即可在 WXML 中直接使用,例如:

<t-segmented options="{{options}}" default-value="{{0}}" />

组件自身声明为独立 Component,其 segmented.json 中设置了"styleIsolation": "apply-shared",并内部依赖t-icon(icon 组件)以支持带图标选项的渲染。

数据化配置:options 与类型定义

分段控制器的选项全部通过options属性数据化配置,官方类型为string[] | number[] | SegmentedItem[],其中:

interface SegmentedItem { value: string | number; // 选项值,change 事件回调中返回 label?: string; // 展示文案,缺省时使用 value 的字符串形式 icon?: string | object; // 选项图标,支持图标名或图标配置对象 disabled?: boolean; // 单个选项是否禁用 }

完整类型定义见 type.ts。

从 segmented.ts 源码 可以看到,组件在options变化时通过updateOptions做归一化处理:

  • 当传入的选项是纯string/number时,自动包装为{ value: option, label: String(option) },因此你可以直接写options="{{['选项A', '选项B']}}";
  • 当传入SegmentedItem对象时,label缺省回退为String(option.value);
  • 图标通过公共工具 calcIcon 归一化:字符串图标名被转换为{ name }对象,对象图标原样透传,最终交给 icon 模板 渲染。

基础用法

对应 base 示例,传入选项对象数组并配合bind:change:

Component({ data: { options: [ { value: 0, label: '选项' }, { value: 1, label: '选项' }, { value: 2, label: '选项' }, ], }, });
<t-segmented options="{{options}}" default-value="{{0}}" />

若需要图标,可在SegmentedItem中声明icon:

optionsWithIcon: [ { value: 0, label: '选项', icon: 'home' }, { value: 1, label: '选项', icon: 'home' }, { value: 2, label: '选项', icon: 'home' }, ],

自适应宽度(block)

设置block属性后,控制器将撑满父元素宽度,选项在内部等分铺开。对应 block 示例:

<t-segmented block options="{{options}}" default-value="{{0}}" />

从 segmented.less 可见,block模式下根节点切换为display: flex; width: 100%,每个选项设置flex: 1; min-width: 0,并将选项内文案做ellipsis溢出省略,保证窄屏下的可用性。非block模式则保持inline-block自适应内容宽度。

组件状态:禁用态控制

禁用态分为整体禁用与单项禁用两个层级(对应 disabled 示例):

  • 整体禁用:设置disabled属性,整个控制器不可交互;
  • 单项禁用:在SegmentedItem中给某个选项设置disabled: true,仅该选项不可点击。
optionsWithDisabled: [ { value: 0, label: '选中' }, { value: 1, label: '默认' }, { value: 2, label: '禁用', disabled: true }, ],
<t-segmented options="{{optionsWithDisabled}}" value="{{valueWithDisabled}}" bind:change="onChangeWithDisabled" />

点击拦截逻辑在源码 handleSelect 中体现:if (disabled || !item || item.disabled) return;同时校验组件级disabled与选项级item.disabled;样式上,禁用项在 segmented.less 中通过pointer-events: none与text-color-disabled颜色呈现。

Props 总览与默认值

根据 README API 章节 与 props.ts,完整属性如下:

| 名称 | 类型 | 默认值 | 说明 | | -- | -- | -- | -- | | style | Object | - | 样式 | | custom-style | Object | - | 样式,一般用于开启虚拟化组件节点场景 | | block | Boolean | false | 是否撑满父元素宽度 | | disabled | Boolean | - | 是否禁用 | | options | Object | [] | 数据化配置选项内容,支持string[] \| number[] \| SegmentedItem[]| | value | String / Number | - | 当前选中的值(受控) | | default-value | String / Number | undefined | 当前选中的值(非受控属性) |

其中value默认值为null(见 props.ts),组件内部用它和defaultValue区分受控/非受控两种模式。

事件与受控/非受控机制

组件仅对外暴露一个事件:

| 名称 | 参数 | 描述 | | -- | -- | -- | | change |(detail: { value: string \| number, selectedOption: SegmentedItem })| 选项值发生变化时触发 |

selectedOption返回的是原始 options 数组中对应的那个选项,方便拿到label、icon等附加信息。

在 segmented.ts 中,组件通过controlledProps声明了受控关系:

controlledProps = [ { key: 'value', event: 'change' }, ];

这意味着:

  • 使用value+bind:change时是受控用法,开发者需要在 change 回调里setData({ value: e.detail.value }),选中态完全由外部数据驱动;
  • 使用default-value时是非受控用法,组件内部维护选中状态,不需要手动更新。

对应示例见 base 示例的 change 回调:

onChangeWithIcon(e) { console.log('onChangeWithIcon:', e.detail); this.setData({ valueWithIcon: e.detail.value }); }

源码原理:滑块动画(thumb)是怎么算出来的

分段控制器的视觉核心是选中项底部的滑动背景块(thumb)。其实现思路在 segmented.wxml 与 segmented.ts 中非常清晰:

  1. 根节点内先渲染一个绝对定位的thumb视图(class 为{{classPrefix}}__thumb,同时挂载t-class-thumb外部样式类),再渲染选项列表;
  2. options或value变化时,通过updateActiveIndex用segmentItems.findIndex((item) => item.value === value)找到当前激活项下标activeIndex;
  3. updateThumb使用公共工具 getRect(底层是createSelectorQuery().boundingClientRect())并行测量"当前激活项"和"选项组容器"的矩形,计算出滑块应平移的距离:
const left = itemRect.left - groupRect.left; this.setData({ thumbStyle: `width: ${itemRect.width}px; transform: translateX(${left}px);`, });
  1. 动画过渡由 CSS 完成:segmented.less 中 thumb 声明了transition: @segmented-transition与will-change: transform, width,切换选项时滑块便平滑滑动到新位置。

值得注意的边界行为:当value为null(未选中任何项)时,activeIndex保持-1,updateThumb直接 return,此时不渲染滑块背景。

深度定制:External Classes 与 CSS Variables

External Classes

组件在源码中声明了三个外部样式类(segmented.ts):

| 类名 | 描述 | | -- | -- | | t-class | 根节点样式类 | | t-class-item | 列表子项样式类 | | t-class-thumb | 动画背景样式类 |

使用时在页面 JSON 中配置styleIsolation为isolated(或apply-shared)后,通过externalClasses传入即可覆盖对应节点的样式,例如调整滑块圆角或选项内边距。

CSS Variables

组件通过 segmented.less 暴露了 7 个 CSS 变量,用于在外部统一改主题(变量默认值取自 tdesign 设计令牌):

| 变量名 | 默认值 | | -- | -- | | --td-segmented-bg-color | @bg-color-component-disabled | | --td-segmented-item-active-bg | @bg-color-container | | --td-segmented-item-active-color | @brand-color | | --td-segmented-item-color | @text-color-primary | | --td-segmented-item-disabled-color | @text-color-disabled | | --td-segmented-item-label-font | @font-body-medium | | --td-segmented-transition | all @anim-duration-base @anim-time-fn-easing |

以 less 源码 为例,变量采用"var + 兜底令牌"的写法:

@segmented-item-active-color: var(--td-segmented-item-active-color, @brand-color);

因此你可以直接在页面 wxss 中覆盖这些变量来整体换肤,例如:

page { --td-segmented-item-active-color: #ff6b00; --td-segmented-item-label-font: 16px; }

测试与验证

仓库为 Segmented 提供了基于miniprogram-simulate的 demo 测试:测试会依次加载base、block、disabled三个示例页面并做快照断言,覆盖了基础选项、自适应宽度与禁用态三种典型场景。如果你修改了组件或示例,可运行npm run test:demo重新生成快照(该文件由脚本自动生成,见文件头注释,手写修改会被覆盖)。

小结

Segmented 分段控制器是 tdesign-miniprogram 中用于单选场景的轻量组件:通过options数据化配置即可快速生成选项,支持字符串/数字/对象三种选项形态、整体与单项两级禁用、受控与非受控两种取值模式,其滑块动画基于getRect测量加 CSS transition 实现,并通过 External Classes 与 CSS Variables 提供了灵活的样式扩展点。接入、配置与深度定制的完整示例均可直接参考仓库中的 _example 目录,其中还包含了 Skyline 渲染示例 供对应渲染框架下使用。

  • 前端
  • UI组件
  • 小程序
  • 设计系统
  • 移动开发

【免费下载链接】tdesign-miniprogram

Wechat MiniProgram and Uniapp UI components lib for TDesign

项目地址:https://gitcode.com/gh_mirrors/tde/tdesign-miniprogram
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询