- 前端
- UI组件
【免费下载链接】zag
Build your design system in React, Solid, Vue, Svelte or Vanilla. Powered by finite state machines
导读
本文以@zag-js/cascade-select的 CHANGELOG.md 为骨架,系统梳理这一基于有限状态机实现的分级联级下拉组件(cascading dropdown)从 1.34.0 首次发布到 1.46.0 的演进脉络。通过将变更日志与 状态机实现、连接层 API、类型定义 及 e2e 测试 相互印证,你将掌握该组件 API 修复、交互细节与各依赖包升级背后的具体原理,并了解如何在 React、Solid、Vue、Svelte 或 Vanilla 项目中安全升级与规避回归。
一、组件定位:用状态机驱动的级联选择器
@zag-js/cascade-select是 zag 仓库中专门实现 cascade select(级联下拉 / 级联选择器)的独立包,其 README 明确将它描述为 "a comprehensive state machine for building cascade select (cascading dropdowns) components with hierarchical data navigation"。它通过 cascade-select.machine.ts 中的createMachine<CascadeSelectSchema>()定义了一套有限状态机,核心状态只有三个:idle(闲置)、focused(触发按钮获得焦点)、open(下拉展开),并在 cascade-select.types.ts 中通过CascadeSelectSchema声明了状态、props、context、computed、action、effect、guard 与 event 的完整结构。
从源码结构看,该包还包含一套完整的部件解剖(anatomy)体系。在 cascade-select.anatomy.ts 中,createAnatomy("cascade-select").parts(...)声明了 root、label、control、trigger、indicator、valueText、clearTrigger、positioner、content、list、item、itemText、itemIndicator 共 13 个部件,对应 shared/src/css/cascade-select.css 中形如[data-scope="cascade-select"][data-part="item"]的样式选择器体系。
CHANGELOG 表明该包与@zag-js/anatomy、@zag-js/core、@zag-js/types、@zag-js/collection、@zag-js/utils、@zag-js/dom-query、@zag-js/popper、@zag-js/rect-utils、@zag-js/dismissable、@zag-js/focus-visible十个依赖包同步版本迭代,本文以其中的非依赖升级类实质性变更为主线。
二、初始发布(1.34.0):Cascade Select 状态机的诞生
在 1.34.0 之前,zag 中并无级联选择器。CHANGELOG 记录该版本(对应 PR #2945)是Cascade Select 状态机的初始发布,由 @anubra266 贡献。这也是 1.34.0 中唯一标注为Minor Changes的条目,而同期其他变更均为 Patch。
从当前源码回看初始设计,可以发现该状态机的几个核心机制从首版就已确立:
- 三态模型:
idle → focused → open的迁移在 cascade-select.machine.ts 中完整保留,idle与focused都带closed标签,open状态则带open标签并挂载trackDismissableElement、trackFocusVisible、computePlacement、scrollToHighlightedItems四个 effect。 - 树形数据集合:cascade-select.collection.ts 提供
collection<T>(options)工厂,底层直接复用@zag-js/collection的TreeCollection;当未传入数据时使用 collection.empty 的空集合兜底。 - "路径即值"模型:
value的类型是string[][](一组完整路径,如[["africa","algeria","adrar"]]),highlightedValue是string[](当前高亮路径),这在 cascade-select.types.ts 的ValueChangeDetails/HighlightChangeDetails中体现:回调同时上报value/items与highlightedValue/highlightedItems。
同一 PR 还顺带修复了一批 API 不一致问题(Patch 部分),为后续迭代奠定了 API 形态。
三、API 一致性修复(1.34.0 Patch):ElementIds 与回调命名对齐
初始发布的同一版本中,另一条 Patch 变更专门修复 API 不一致(commitf64e81f),共三处,逐条对照源码解读如下:
ElementIds中list参数类型修正(number → string):在 cascade-select.types.ts 中,list与item的签名现在都是((valuePath: string) => string) | undefined,即根据"值路径"(如"asia,india")生成对应列表/条目的 DOM id。底层 cascade-select.dom.ts 的getListId/getItemId也接受字符串值路径,默认生成cascade-select:${id}:list:${value}与cascade-select:${id}:item:${value}。highlightedItem更名为highlightedItems:API 与 context 中统一使用复数形式,与HighlightChangeDetails回调的highlightedItems: T[]字段保持一致。当前 connect.ts 与 types.ts 均导出highlightedItems(高亮路径上各级节点数组)。shouldCloseOnSelectHighlightedguard 修复:原先在判断是否关闭时把整个路径数组传给了isBranchNode,现改为取路径最后一个节点再判断,即只对"叶节点"才允许closeOnSelect生效。对应实现见 cascade-select.machine.ts:const node = last(items); return prop("closeOnSelect") && node != null && !collection.isBranchNode(node)。
这三处修复说明:首版级联选择器在"值路径(value path)"与"索引路径(index path)"两类路径概念上做了明确区分——前者以节点 value 组成(用于 id 生成与回调),后者以数组下标组成(用于树内定位,见IndexPath),理解这一点是正确使用 API 的前提。
四、交互与行为修复(1.41.0 ~ 1.44.0)
1.42.0 之前多为依赖升级,从 1.41.0 起陆续出现与本组件交互行为直接相关的修复。
4.1 新增>赞
- 前端
- UI组件
【免费下载链接】zag
Build your design system in React, Solid, Vue, Svelte or Vanilla. Powered by finite state machines
相关推荐
zag 中 @zag-js/select 的版本演进全解:状态机 Select 组件从 0.1.0 到 1.46.0 的 API 变迁与实现要点
zag 中 @zag js/select 的版本演进全解:状态机 Select 组件从 0.1.0 到 1.46.0 的 API 变迁与实现要点 本文基于 pa
前端UI组件@zag-js/menu 状态机深度解读:从 CHANGELOG 看 Zag 菜单组件的演进与实现原理
@zag js/menu 状态机深度解读:从 CHANGELOG 看 Zag 菜单组件的演进与实现原理 @zag js/menu 是 Zag 生态中基于有限状态
前端UI组件Zag.js Cascade Select 状态机全解析:构建支持无限层级数据的级联下拉组件
Zag.js Cascade Select 状态机全解析:构建支持无限层级数据的级联下拉组件 导读 @zag js/cascade select 是 Zag 项
前端UI组件