资讯动态

TDesign Uniapp Segmented 分段控制器组件实战:从引入配置到源码实现解析

发布时间:2026/10/16 2:41:20 来源:尧图企业网站定制
前端UI组件小程序设计系统移动开发【免费下载链接】tdesign-miniprogramWechat MiniProgram and Uniapp UI components lib for TDesign项目地址https://gitcode.com/gh_mirrors/tde/tdesign-miniprogram点击查看免费下载Segmented分段控制器是 TDesign Uniapp 组件库中用于「展示多个选项并允许用户选择其中单个选项」的基础交互组件广泛应用于筛选条件切换、视图模式切换、Tab 类分段导航等单选项互斥场景。本文以仓库内 segmented/README.md 为骨架结合组件源码、类型定义、样式文件与示例页面系统讲解该组件的引入方式、全部配置项、受控与非受控用法、禁用状态、自适应宽度、事件机制以及拇指滑块动画的底层实现原理帮助你在一站式开发中快速落地并理解其内部机制。组件定位与核心特性从 README 的组件描述可以看出Segmented 的核心交互模型是「多选项、单选、互斥」与单选框Radio语义相近但呈现形态为横向分段式控制器视觉上更紧凑、操作路径更短。组件名称t-segmented由前缀t与组件名segmented拼接而来前缀定义见 common/config.js。其核心能力包括数据化配置选项通过options属性一次性传入全部选项支持字符串数组、数字数组或结构化对象数组受控 / 非受控双模式支持v-model:value语法糖也支持default-value非受控用法基础 / 自适应宽度两种形态block属性控制是否撑满父元素宽度整组禁用与单项禁用既有控制器级disabled也支持选项级disabled图标选项选项可配置 icon与文字组合展示滑动拇指动画选中背景thumb会跟随点击选项平滑移动。安装与引入方式安装组件库在项目根目录执行npm i tdesign/uniapp安装完成后在main.ts中引入组件库样式推荐 Less 版本以 rpx 为单位import tdesign/uniapp/theme.less; // 或引入编译后的 CSSimport tdesign/uniapp/theme.css;推荐easycom 自动引入对于 Uniapp 项目推荐使用 easycom 模式引入组件配置后无需手动import即可在模板中直接使用t-segmented /。在pages.json中添加如下配置CLI 模式node_modules 下使用tdesign/uniapp{ easycom: { custom: { ^t-(.*): tdesign/uniapp/$1/$1.vue } } }HBuilderX 模式uni_modules 下使用tdesign-uniapp{ easycom: { custom: { ^t-(.*): /uni_modules/tdesign-uniapp/components/$1/$1.vue } } }配置完成后模板中可直接书写t-segmented :optionsoptions /。完整引入步骤见 TDesign Uniapp 快速开始文档。手动引入若不使用 easycom可在script中手动导入与示例 base/index.vue 的写法一致import TSegmented from tdesign/uniapp/segmented/segmented.vue;随后在components中注册即可在模板中使用。注意组件库只提供按需导入方式不支持全量导入全量导入在小程序环境下存在兼容性问题。组件类型基础与自适应宽度基础用法Segmented 最基本的使用方式是传入options选项数组并配合value/default-value控制选中项。参考示例 base/index.vuetemplate t-segmented :optionsoptions :default-value0 / /template script export default { data() { return { options: [ { value: 0, label: 选项 }, { value: 1, label: 选项 }, { value: 2, label: 选项 }, ], }; }, }; /script基础形态下组件宽度由其内容撑开选项按内容宽度排列。自适应宽度block当需要让分段控制器占满父容器整行宽度、各选项均分空间时设置block属性即可参考示例 block/index.vuetemplate t-segmented block :optionsoptions :default-value0 / /template从样式实现 segmented.less 可以看到block形态下根节点变为display: flex; width: 100%每个选项设置flex: 1; min-width: 0因此所有选项会等分父容器宽度同时选项内部文字通过overflow: hidden; text-overflow: ellipsis在空间不足时自动省略保证超长文案不撑破布局。选项数据格式与 options 详解options是组件的核心数据源TS 类型为string[] | number[] | SegmentedItem[]。结构化选项SegmentedItem的完整定义见 type.tsexport interface SegmentedItem { value: string | number; label?: string; icon?: string | object; disabled?: boolean; }value选项唯一标识必填类型为字符串或数字label展示文案缺省时组件会回退为value的字符串形式icon选项图标可为图标名字符串或图标配置对象disabled单项禁用标记。从组件源码 segmented.vue 的updateOptions方法可以看到数据归一化的过程updateOptions(options) { if (!options?.length) return; const segmentItems options.map((option) { if (typeof option string || typeof option number) { return { value: option, label: String(option) }; } return { ...option, label: coalesce(option.label, String(option.value)), icon: option.icon ? calcIcon(option.icon) : null, }; }); this.segmentItems segmentItems; },也就是说纯字符串 / 数字选项会被自动包装为{ value, label: String(value) }即选项的展示文案默认就是其值本身结构化选项未提供label时label回退为value的字符串形式coalesce为取值工具函数见 common/utils.js图标经过calcIcon归一化为统一的对象形态{ name: ... }。该归一化逻辑通过watch监听options并immediate: true立即执行因此 options 数据在运行时动态更新也会被自动处理。受控与非受控value 与 default-valueSegmented 同时支持受控与非受控两种选中值管理方式这也是 README 中value与default-value两个属性并存的由来。受控模式v-modelvalue为受控属性支持语法糖v-model:value。受控模式下选中值由外部数据驱动变化时需通过change事件回写示例template t-segmented :optionsoptions :valuecurrent changeonChange / /template script export default { data() { return { current: 1, options: [微信, 支付宝, 银联], }; }, methods: { onChange(e) { this.current e.value; }, }, }; /script非受控模式default-valuedefault-value为非受控属性只在初始化时生效之后选中态由组件内部维护。源码中dataValue的初始化正是二者的优先级合并dataValue: coalesce(this.value, this.defaultValue),即value优先于default-value。底层实现controlledProps受控机制的底层来自uniComponent的controlledProps配置见 segmented.vuecontrolledProps: [ { key: value, event: change, }, ],该声明将value与change事件绑定为受控对使组件自动支持v-model:value。同时源码中通过watch监听外部value变化并同步到内部dataValue再触发updateActiveIndex更新选中态形成完整闭环。相关受控基座逻辑可参考 common/src/control.js 中的useControl实现。组件状态控制器禁用态整组禁用控制器级disabled属性为 Boolean 类型设置后整组不可点击。在模板中t-segmented disabled :optionsoptions :default-value0 /单项禁用除了整组禁用还可以通过SegmentedItem.disabled对单个选项禁用参考示例 disabled/index.vuetemplate t-segmented :optionsoptions :valuecurrent changeonChange / /template script export default { data() { return { current: 0, options: [ { value: 0, label: 选中 }, { value: 1, label: 默认 }, { value: 2, label: 禁用, disabled: true }, ], }; }, }; /script上述示例中第三个选项「禁用」不可点击。从模板渲染逻辑看选项的禁用态由「整组 disabled 或 单项 item.disabled」共同决定[active, index activeIndex], [disabled, disabled || item.disabled],样式层面见 segmented.less禁用项通过pointer-events: none屏蔽点击并以--td-segmented-item-disabled-color对应的禁用文本色展示交互层面handleSelect中对禁用态做了二次拦截if (disabled || !item || item.disabled) return;事件机制changechange事件在选项值发生变化时触发回调参数结构为(context: { value: string | number, selectedOption: SegmentedItem }) voidvalue新选中的选项值selectedOption选中的原始选项对象即options中对应的原始条目。事件触发路径见handleSelectsegmented.vuehandleSelect(index) { const { segmentItems, activeIndex, disabled, options } this; const item segmentItems[index]; if (disabled || !item || item.disabled) return; if (index activeIndex) return; this._trigger(change, { value: item.value, selectedOption: options[index], }); },值得注意的两个细节点击当前已选中项不会触发 change源码中if (index activeIndex) return;保证了重复点击不产生无效事件selectedOption 返回的是原始 options 条目组件在_trigger时取的是options[index]而非归一化后的segmentItems[index]保证回调中拿到的是开发者传入的原始数据对象。图标选项当SegmentedItem.icon为字符串时会被渲染为对应的 TDesign 图标内部使用t-icon组件calcIcon将其归一化为{ name: icon }。示例 base/index.vue 中展示了带图标选项的写法template t-segmented :optionsoptionsWithIcon :valuevalueWithIcon changeonChangeWithIcon / /template script export default { data() { return { valueWithIcon: 0, optionsWithIcon: [ { value: 0, label: 选项, icon: home }, { value: 1, label: 选项, icon: home }, { value: 2, label: 选项, icon: home }, ], }; }, }; /scripticon同时也支持对象形态即string | object可在需要自定义图标资源时传入图标配置对象。图标与文字在选项内部通过 flex 布局水平居中排列图标与文字之间保留calc(spacer / 2)的间距见 segmented.less。样式定制External Classes 与 CSS VariablesExternal Classes 外部样式类组件暴露了三个外部样式类用于在不侵入组件内部样式的条件下覆盖根节点与关键子节点样式| 类名 | 描述 | | -- | -- | | t-class | 根节点样式类 | | t-class-item | 列表子项样式类 | | t-class-thumb | 动画背景样式类 |在组件源码中它们通过externalClasses声明注册t为组件前缀见 common/config.jsexternalClasses: [${prefix}-class, ${prefix}-class-thumb, ${prefix}-class-item],使用方式是在页面或父组件的样式中编写同名类例如t-segmented classt-class :optionsoptions /.t-class { border: 1rpx solid #dcdcdc; } .t-class-item { letter-spacing: 2rpx; } .t-class-thumb { box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1); }注意t-class-thumb作用于选中项背后的滑块背景其宽度与位移由组件内部动态计算外部类只用于叠加额外视觉效果。CSS Variables 样式变量组件在 README.md 中声明了下列 CSS 变量可在任意上层作用域页面或 App覆盖以完成主题定制| 变量名 | 默认值 | 描述 | | -- | -- | -- | | --td-font-size-m | 32rpx | 选项图标字号 | | --td-segmented-bg-color | bg-color-component-disabled | 控制器底色 | | --td-segmented-item-active-bg | bg-color-container | 选中项thumb背景色 | | --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 | thumb 位移动画过渡 |这些变量在样式实现 segmented.less 中通过var()的第二个参数绑定到设计令牌默认值例如segmented-bg-color: var(--td-segmented-bg-color, bg-color-component-disabled); segmented-item-active-color: var(--td-segmented-item-active-color, brand-color); segmented-transition: var(--td-segmented-transition, all anim-duration-base anim-time-fn-easing);也就是说所有颜色与动效默认值均来自 TDesign 设计令牌如bg-color-component-disabled、brand-color、anim-duration-base未覆盖变量时自动跟随主题体系覆盖变量时即可实现局部品牌化定制。示例性覆盖写法page { --td-segmented-bg-color: #f0f2f5; --td-segmented-item-active-color: #0052d9; }源码实现原理thumb 滑块的渲染与定位Segmented 最具有代表性的交互是选中背景thumb的平滑滑动。从 segmented.vue 模板结构看组件渲染层级为view.t-segmented └── view.t-segmented__group相对定位容器 ├── view.t-segmented__thumb绝对定位滑块背景stylethumbStyle └── view.t-segmented__item × N每个选项z-index: 1thumb 是一个绝对定位元素其尺寸与位置完全由 JS 动态计算得出核心是updateThumb方法updateThumb() { const { activeIndex, classPrefix } this; if (activeIndex 0) return; const groupClass .${classPrefix}__group; const itemClass .${classPrefix}-item-${activeIndex}; Promise.all([getRect(this, itemClass), getRect(this, groupClass)]).then(([itemRect, groupRect]) { if (itemRect groupRect) { const left itemRect.left - groupRect.left; this.thumbStyle width: ${itemRect.width}px; transform: translateX(${left}px);; } }); },该方法的实现要点测量通过uni.createSelectorQuery封装的getRect见 common/utils.js同时获取当前激活选项与__group容器的位置矩形计算滑块宽度取激活选项的width横向位移取激活选项左边缘相对容器左边缘的偏移量itemRect.left - groupRect.left动画滑块通过transform: translateX移动配合样式层transition: var(--td-segmented-transition)实现平滑滑动而非生硬跳变。updateThumb的触发时机包括组件mounted后、dataValue变化导致激活索引更新后$nextTick中调用以及segmentItems变化后确保首次渲染、切换选中、选项数据变更三种场景下滑块位置都保持正确。若当前没有选中项activeIndex 0则跳过测量thumb 保持初始位置。完整属性速查表为便于查阅汇总 README 中全部 Props 与说明| 属性 | 类型 | 默认值 | 说明 | | -- | -- | -- | -- | | custom-style | Object | - | 自定义样式 | | block | Boolean | false | 是否撑满父元素宽度 | | disabled | Boolean | - | 是否禁用 | | options | Object | [] | 数据化配置选项内容string[] \| number[] \| SegmentedItem[]| | value | String / Number | - | 当前选中的值支持v-model:value| | default-value | String / Number | - | 当前选中的值非受控属性 |事件change参数(context: { value: string \| number, selectedOption: SegmentedItem })选项值发生变化时触发。总结与最佳实践结合 README 与源码使用 Segmented 时有几个值得留意的实践要点优先 easycom配置一次pages.json的 easycom 规则即可全项目免 import 使用t-segmented /是最省事的接入方式受控与业务状态联动当选中值需要与页面其他区域联动如切换筛选后刷新列表时使用:valuechange双向回写仅需默认态时用default-value即可善用单项禁用在展示类场景如会员等级、套餐档次中通过SegmentedItem.disabled表达「暂不可用」比整组禁用更贴近业务选项图标需要图标时记得options使用结构化SegmentedItem而非纯字符串数组主题统一颜色与动画默认跟随 TDesign 设计令牌品牌定制只需覆盖 README 列出的 CSS 变量无需侵入组件内部样式注意重复点击点击当前已选中项不会触发change业务代码无需额外做去重判断。如果你需要对照完整示例页面可直接查看 Segmented 示例聚合页 及其下的 base、block、disabled 三个分示例深入阅读实现可继续跟踪 segmented.vue、segmented.less 与 type.ts。赞分享前端UI组件小程序设计系统移动开发【免费下载链接】tdesign-miniprogramWechat MiniProgram and Uniapp UI components lib for TDesign项目地址https://gitcode.com/gh_mirrors/tde/tdesign-miniprogram点击查看免费下载相关推荐tdesign-uniapp Stepper 步进器组件从 Props 配置到源码实现全解析tdesign uniapp Stepper 步进器组件从 Props 配置到源码实现全解析 本文是一份围绕 TDesign 开源组件库中 uniapp 版前端UI组件小程序设计系统移动开发tdesign-miniprogram Segmented 分段控制器从接入、受控值到源码级原理全解析tdesign miniprogram Segmented 分段控制器从接入、受控值到源码级原理全解析 本文以 Segmented 分段控制器官方文档 htt前端UI组件小程序设计系统移动开发TDesign UniApp CountDown 倒计时组件实战从参数配置到计时引擎源码解析TDesign UniApp CountDown 倒计时组件实战从参数配置到计时引擎源码解析 CountDown 是 TDesign UniApp tde前端UI组件小程序设计系统移动开发上一篇从零跑通 CPython给新手的完整上手指南下一篇PostCSS Preset Env指南如何使用未来CSS语法特性 创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑