组件 · 数据展示
Tree 树形目录
展示组织、目录和分类的层级结构,支持搜索、行选择、意图复选及异步分支加载;焦点、选择和勾选相互独立。
引入
从 @selrux/ui/tree 引入 Tree 及所需公开类型,如 TreeNode、TreeCheckedState、TreeApi。组件子路径自动引入局部 CSS,无需额外引入全量样式。主题、语言、方向按需使用 @selrux/ui/config-provider。资料为本地 preview,先核对实际安装版本与来源状态。
本地实现子路径:@selrux/ui/tree、@selrux/headless/tree。UI 不直接引用 Headless 源码,类型从 Headless 公开入口复用。
- UI
Tree<T>:组合搜索区、状态区与树视口。 - Headless
TreeRoot<T>:持有模型和行为,不带品牌样式;children 为组合内容。 TreeSearch:绑定查询、输入组合态与输入键盘行为。TreeViewport<T>:提供窗口化与非窗口化渲染,接收节点内容 render prop。TreeItem:管理交互壳、稳定 id、ARIA 与节点状态;不由消费者手写 keydown。TreeBranchAction:父行内的加载、分页和重试入口,支持 Alt+Enter 进入。useTreeContext<T>:读取快照与动作;调用方不能直接修改 Map/Set。
何时使用
Tree 用于组织、目录、分类等层级数据,支持展开、搜索、行选择和复选。扁平选项使用 Select;在输入框中选择层级值需应用组合弹层,Tree 不提供 TreeSelect。
默认启用连接线和固定行高虚拟列表;filterable 开启搜索,checkable 开启复选。data、searchFields、getSearchData 保持稳定引用;更新节点时传入新不可变数据,不在每次受控输入更新时重建整棵树。
搜索规则
默认对 name 与 String(value) 做忽略大小写的子串匹配,采用 NFC 规范化。多个空白分隔词之间 AND,启用字段之间 OR;不自动拼音、正则或简繁转换。额外字段必须加入 searchFields,例如 searchData.fullName、searchData.alias。
getSearchData 必须纯函数,在索引建立时运行。context.pathNames() 只含祖先名称,当前节点自行拼接;静态 node.searchData 与派生结果合并,同名派生值优先。可以直接传入服务端预处理的 searchData.fullName,两种方式均不替换节点名称。
filter 模式保留匹配项及祖先并临时展开路径,清空后恢复原展开及滚动位置;highlight 保留当前视图,只标记匹配。filterNode 可覆盖本地匹配,仍须纯函数,不自动在 Worker 执行用户函数。
输入法组合完成后提交查询,默认合并等待 120ms;计算期间保留旧结果并暂停选择提交。隐藏字段命中只显示“匹配”,不会伪造名称高亮或输出完整隐藏路径。
本地搜索仅覆盖已提供及已加载数据,不自动遍历下载未知分支。全量服务端搜索使用 remote 与 searchResult,快照与取消约束见异步加载章节。
勾选意图与提交完整性
级联时最近祖先(含自身)的显式规则生效;没有规则即未选。比如 includeKeys=[部门]、excludeKeys=[小组] 表示选择部门其余成员,未来加载到该小组下的成员仍排除。小组内再显式 include 某成员允许恢复该成员;不能把后代 include 误判为冗余。key 同时出现在两数组是非法输入,不能靠遍历顺序裁决。
用户切换节点时清理该节点可达范围内被此次规则覆盖的旧规则;保留禁用隔离子树内的规则。未知 key 的祖先关系不可猜测,保留为 unresolved。strict 模式不继承,不产生半选,excludeKeys 必须为空;运行时切换 checkStrictly 要由调用方明确重置/转换状态,不隐式改写。
disabled / disableCheckbox 节点阻断祖先级联,父级汇总排除该隔离分支;其后代可由自己的显式规则独立选择。checkable=false 只隐藏自身复选,允许向子节点传导。所有可勾选后代均被隔离时,普通可勾选父节点按自身规则处理;纯结构节点没有可操作后代则不产生勾选。
父节点展示由后代结果派生:全部已知可勾选范围选中且分支完整则全选,部分选中则半选。未完整分支只有明确覆盖未来的 include 意图才能显示全选,否则已选部分显示半选并附“子节点未全部加载”;全未选仍未选。祖先派生全选不自动写成新的 include 意图,避免无意选择未来节点。
resolveChecked 为 O(N) 枚举,只在提交等明确动作调用;complete=false 时不得把部分叶子当完整清单。
不提供含义模糊的 checkedKeys 快捷状态。表单/提交调用 resolveChecked({strategy:'all'|'leaf'|'parent'}),返回已加载有效节点的 keys、values、unresolvedKeys、incompleteBranchKeys 和 complete。leaf 只含确认叶子;parent 是可安全压缩的完整勾选分支,遇到排除或未完整数据不能假装完成。该方法不发请求;只有 complete=true 才能当作完整枚举清单。提交意图结构则由业务后端另行约定,Tree 不宣称它是授权清单。
活动焦点、selectedKeys 行选择、checkedState 复选是独立状态。点击名称选择行,展开图标只展开,复选指示只勾选;方向键只导航。搜索不会缩小父级勾选范围,隐藏后代仍受影响;仅选命中项时逐项勾选或使用 strict。
同一状态只能选受控或非受控,生命周期中不可切换。受控回调只提议,父级回传前仍以 props 为准;相同状态不回调。禁用、加载中重复操作及取消事件不得产生重复提交。默认值只初始化,不随新加载节点重新执行。
data 引用或 dataVersion 变化均取消旧请求并清空旧分支缓存,保留 key 级选择意图为 unresolved 直到重新定位;因此普通输入重渲染必须保持 data 引用稳定。需保留加载数据时,调用方先从快照导出完整已加载结构再替换。显式切换业务数据集时调用方一并重置受控选择,不能跨租户沿用状态。
演练场
代码演示
基础树与连接线
连接线开关
五级目录与多分支
六档尺寸
搜索 name、value 与隐藏路径
试试:前端、FE-001、研发中心 前端、Web。清空恢复原展开;不存在的词会显示零匹配。
自定义匹配与仅高亮
受控展开、行选择与复选
行选择:无;展开:team;包含:无;排除:无
父选子排除与半选
严格复选与结构节点
节点级限制
异步分页与重试
远程搜索、加载与重试
自定义内容
四级目录与多行标题
空态与禁用
无效数据与恢复
表单校验
定位、展开与快照
英文、暗色与 RTL
Headless 无样式组合
十万节点虚拟列表
API
Tree
开箱即用的数据驱动树;默认固定行高虚拟化。
<T = unknown>(props: TreeProps<T>) => JSX.Element| 属性 | 类型 | 可选 | 默认值 / 证据 | 说明 | 来源 |
|---|---|---|---|---|---|
| data | readonly TreeNode<T>[] | 否 | 未声明;见说明/约束 | 不可变数据基线;引用变化重置加载代次。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| showLine | boolean | 是 | 未声明;见说明/约束 | 默认开启连接线,关闭后保持缩进。 | ui: @selrux/ui/dist/types/components/tree/tree-props.d.ts |
| size | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | 是 | md(继承配置域尺寸,默认 md。) | 继承配置域尺寸,默认 md。 | ui: @selrux/ui/dist/types/components/tree/tree-props.d.ts |
| renderNode | ((node: TreeNode<T>, context: TreeNodeRenderContext) => ReactNode) | 是 | 未声明;见说明/约束 | 默认展示 name,可替换内容但不能覆盖 role 或焦点。 | ui: @selrux/ui/dist/types/components/tree/tree-props.d.ts |
| renderIcon | ((node: TreeNode<T>, context: TreeRenderContext) => ReactNode) | 是 | 未声明;见说明/约束 | 装饰图标,不承担展开动作。 | ui: @selrux/ui/dist/types/components/tree/tree-props.d.ts |
| classNames | Partial<Record<TreeSemanticSlot, string>> | 是 | 未声明;见说明/约束 | 语义 class 覆盖。 | ui: @selrux/ui/dist/types/components/tree/tree-props.d.ts |
| styles | Partial<Record<TreeSemanticSlot, CSSProperties>> | 是 | 未声明;见说明/约束 | 语义内联样式覆盖。 | ui: @selrux/ui/dist/types/components/tree/tree-props.d.ts |
| emptyText | string | 是 | 未声明;见说明/约束 | 空数据文案覆盖。 | ui: @selrux/ui/dist/types/components/tree/tree-props.d.ts |
| noMatchText | string | 是 | 未声明;见说明/约束 | 零匹配文案覆盖。 | ui: @selrux/ui/dist/types/components/tree/tree-props.d.ts |
| loadingText | string | 是 | 未声明;见说明/约束 | 搜索/加载中的文案覆盖。 | ui: @selrux/ui/dist/types/components/tree/tree-props.d.ts |
| className | string | 是 | 未声明;见说明/约束 | react-native: @types/react/index.d.ts | |
| aria-describedby | string | 是 | 未声明;见说明/约束 | Identifies the element (or elements) that describes the object. | react-native: @types/react/index.d.ts |
| aria-label | string | 是 | 未声明;见说明/约束 | Defines a string value that labels the current element. | react-native: @types/react/index.d.ts |
| onClick | MouseEventHandler<HTMLDivElement> | 是 | 未声明;见说明/约束 | react-native: @types/react/index.d.ts | |
| dataVersion | string | number | 是 | 未声明;见说明/约束 | 业务数据源重置标记。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| disabled | boolean | 是 | 未声明;见说明/约束 | 禁止用户操作。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| invalid | boolean | 是 | 未声明;见说明/约束 | 错误语义。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| expandedKeys | readonly string[] | 是 | 未声明;见说明/约束 | 受控用户展开集合。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| defaultExpandedKeys | readonly string[] | 是 | 未声明;见说明/约束 | 初始展开集合。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| defaultExpandDepth | number | 是 | 未声明;见说明/约束 | 初始展开层数,不自动请求。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| onExpandedChange | ((keys: readonly string[], details: TreeExpandedDetails) => void) | 是 | 未声明;见说明/约束 | 展开提议。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| selectionMode | "none" | "single" | "multiple" | 是 | 未声明;见说明/约束 | 行选择与复选独立。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| selectedKeys | readonly string[] | 是 | 未声明;见说明/约束 | 受控行选择。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| defaultSelectedKeys | readonly string[] | 是 | 未声明;见说明/约束 | 初始行选择。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| onSelectionChange | ((keys: readonly string[], details: TreeSelectionDetails) => void) | 是 | 未声明;见说明/约束 | 行选择提议。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| checkable | boolean | 是 | 未声明;见说明/约束 | 显示复选能力。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| checkStrictly | boolean | 是 | 未声明;见说明/约束 | 独立复选,不向父子传导。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| checkedState | TreeCheckedState | 是 | 未声明;见说明/约束 | 受控包含/排除规则。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| defaultCheckedState | TreeCheckedState | 是 | 未声明;见说明/约束 | 初始复选规则。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| onCheckedChange | ((state: TreeCheckedState, details: TreeCheckedDetails) => void) | 是 | 未声明;见说明/约束 | 用户复选提议,加载完成不触发。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| filterable | boolean | 是 | 未声明;见说明/约束 | UI 可据此组合搜索框。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| searchValue | string | 是 | 未声明;见说明/约束 | 受控查询,输入即时回调,计算延迟合并。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| defaultSearchValue | string | 是 | 未声明;见说明/约束 | 初始查询。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| onSearch | ((query: string) => void) | 是 | 未声明;见说明/约束 | 搜索值提议。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| searchMode | "filter" | "highlight" | 是 | 未声明;见说明/约束 | 过滤或仅标记当前视图。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| remote | boolean | 是 | 未声明;见说明/约束 | 由外部提供搜索快照。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| searchResult | TreeSearchResult<T> | 是 | 未声明;见说明/约束 | 外部带代次的搜索结果。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| loadChildren | TreeLoadChildren<T> | 是 | 未声明;见说明/约束 | 网络请求适配。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| loadConcurrency | number | 是 | 4(并发上限,默认 4。) | 并发上限,默认 4。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| loadTimeout | number | 是 | 30000(请求超时毫秒,默认 30000。) | 请求超时毫秒,默认 30000。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| onLoadError | ((error: Error, details: TreeErrorDetails) => void) | 是 | 未声明;见说明/约束 | 分支错误观察。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| onDataError | ((error: Error, details: TreeErrorDetails) => void) | 是 | 未声明;见说明/约束 | 数据/搜索错误观察。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| virtual | boolean | 是 | true(固定行高虚拟化,默认 true。) | 固定行高虚拟化,默认 true。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| itemSize | number | 是 | 32(固定行高,默认 32。) | 固定行高,默认 32。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| height | number | 是 | 320(视口高度,默认 320。) | 视口高度,默认 320。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| overscan | number | 是 | 6(额外窗口行,默认 6。) | 额外窗口行,默认 6。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| onContentScroll | ((details: VirtualListScrollDetails) => void) | 是 | 未声明;见说明/约束 | 滚动几何变化。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| apiRef | Ref<TreeApi<T>> | 是 | 未声明;见说明/约束 | 实例动作,与 DOM ref 分离。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| ref | Ref<HTMLDivElement> | 是 | 未声明;见说明/约束 | 根 DOM。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| searchFields | readonly string[] | 是 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/search/search-types.d.ts | |
| getSearchData | ((node: TreeNode<T>, context: TreePathContext<T>) => TreeSearchData) | 是 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/search/search-types.d.ts | |
| filterNode | ((query: string, node: TreeNode<T>, context: TreePathContext<T>) => boolean) | 是 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/search/search-types.d.ts |
其余 272 个 React 原生属性按继承汇总;关键原生属性已展开。
TreeApi
Tree 对外实例接口。
TreeApi<T>| 属性 | 类型 | 可选 | 默认值 / 证据 | 说明 | 来源 |
|---|---|---|---|---|---|
| scrollToKey | (key: string, options?: { align?: "start" | "center" | "end" | "auto"; }) => "visible" | "not-visible" | "not-found" | 否 | 未声明;见说明/约束 | 当前不可见时不隐式展开。 | headless: @selrux/headless/dist/types/components/tree/contracts/api.d.ts |
| revealKey | (key: string, options?: { focus?: boolean; }) => "visible" | "pending" | "not-found" | 否 | 未声明;见说明/约束 | 提议展开已知祖先;受控父级尚未接受时返回 pending。 | headless: @selrux/headless/dist/types/components/tree/contracts/api.d.ts |
| reloadNode | (key: string) => void | 否 | 未声明;见说明/约束 | 原子刷新分支,失败保留旧数据。 | headless: @selrux/headless/dist/types/components/tree/contracts/api.d.ts |
| retryLoad | (key: string) => void | 否 | 未声明;见说明/约束 | 重试失败页。 | headless: @selrux/headless/dist/types/components/tree/contracts/api.d.ts |
| resolveChecked | (options?: { strategy?: "all" | "leaf" | "parent"; }) => TreeCheckedResult | 否 | 未声明;见说明/约束 | 按需枚举,未加载范围通过 complete 标识。 | headless: @selrux/headless/dist/types/components/tree/contracts/api.d.ts |
| getSnapshot | () => TreeSnapshot<T> | 否 | 未声明;见说明/约束 | 返回副本,不允许外部修改内部状态。 | headless: @selrux/headless/dist/types/components/tree/contracts/api.d.ts |
其余 0 个 React 原生属性按继承汇总;关键原生属性已展开。
TreeChangeDetails
一次操作的变更来源;加载完成不产生伪用户变更。
TreeChangeDetails| 属性 | 类型 | 可选 | 默认值 / 证据 | 说明 | 来源 |
|---|---|---|---|---|---|
| key | string | 否 | 未声明;见说明/约束 | 触发节点。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
| reason | "pointer" | "keyboard" | "api" | 否 | 未声明;见说明/约束 | 操作来源。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
| originalEvent | Event | 是 | 未声明;见说明/约束 | 原始 DOM 事件。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
其余 0 个 React 原生属性按继承汇总;关键原生属性已展开。
TreeCheckedDetails
复选状态变更。
TreeCheckedDetails| 属性 | 类型 | 可选 | 默认值 / 证据 | 说明 | 来源 |
|---|---|---|---|---|---|
| checked | boolean | 否 | 未声明;见说明/约束 | 目标勾选状态。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
| key | string | 否 | 未声明;见说明/约束 | 触发节点。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
| reason | "pointer" | "keyboard" | "api" | 否 | 未声明;见说明/约束 | 操作来源。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
| originalEvent | Event | 是 | 未声明;见说明/约束 | 原始 DOM 事件。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
其余 0 个 React 原生属性按继承汇总;关键原生属性已展开。
TreeCheckedResult
显式枚举结果;complete=false 不可当作完整提交清单。
TreeCheckedResult| 属性 | 类型 | 可选 | 默认值 / 证据 | 说明 | 来源 |
|---|---|---|---|---|---|
| keys | readonly string[] | 否 | 未声明;见说明/约束 | 已加载的有效节点。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
| values | readonly (string | number)[] | 否 | 未声明;见说明/约束 | 与 keys 顺序一致的业务值。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
| unresolvedKeys | readonly string[] | 否 | 未声明;见说明/约束 | 尚无法定位的意图节点。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
| incompleteBranchKeys | readonly string[] | 否 | 未声明;见说明/约束 | 受选择影响但尚未完整的分支。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
| complete | boolean | 否 | 未声明;见说明/约束 | 是否完成枚举。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
其余 0 个 React 原生属性按继承汇总;关键原生属性已展开。
TreeCheckedState
勾选规则的公开契约。
TreeCheckedState| 属性 | 类型 | 可选 | 默认值 / 证据 | 说明 | 来源 |
|---|---|---|---|---|---|
| includeKeys | readonly string[] | 否 | 未声明;见说明/约束 | 包含当前节点及未来可达子项。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
| excludeKeys | readonly string[] | 否 | 未声明;见说明/约束 | 排除当前子分支;最近的显式规则优先。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
其余 0 个 React 原生属性按继承汇总;关键原生属性已展开。
TreeChildrenPage
当前父级的一页直接子节点。
TreeChildrenPage<T>| 属性 | 类型 | 可选 | 默认值 / 证据 | 说明 | 来源 |
|---|---|---|---|---|---|
| nodes | readonly TreeNode<T>[] | 否 | 未声明;见说明/约束 | 按返回顺序追加。 | headless: @selrux/headless/dist/types/components/tree/contracts/loading.d.ts |
| nextCursor | null | string | 否 | 未声明;见说明/约束 | null 为终页。 | headless: @selrux/headless/dist/types/components/tree/contracts/loading.d.ts |
其余 0 个 React 原生属性按继承汇总;关键原生属性已展开。
TreeErrorDetails
错误上下文不包含整份业务数据。
TreeErrorDetails| 属性 | 类型 | 可选 | 默认值 / 证据 | 说明 | 来源 |
|---|---|---|---|---|---|
| phase | "data" | "search" | "load" | 否 | 未声明;见说明/约束 | 出错阶段。 | headless: @selrux/headless/dist/types/components/tree/contracts/loading.d.ts |
| key | string | 是 | 未声明;见说明/约束 | 出错节点;整体索引错误时省略。 | headless: @selrux/headless/dist/types/components/tree/contracts/loading.d.ts |
其余 0 个 React 原生属性按继承汇总;关键原生属性已展开。
TreeExpandedDetails
展开状态变更。
TreeExpandedDetails| 属性 | 类型 | 可选 | 默认值 / 证据 | 说明 | 来源 |
|---|---|---|---|---|---|
| expanded | boolean | 否 | 未声明;见说明/约束 | 目标展开状态。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
| key | string | 否 | 未声明;见说明/约束 | 触发节点。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
| reason | "pointer" | "keyboard" | "api" | 否 | 未声明;见说明/约束 | 操作来源。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
| originalEvent | Event | 是 | 未声明;见说明/约束 | 原始 DOM 事件。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
其余 0 个 React 原生属性按继承汇总;关键原生属性已展开。
TreeLoadChildren
调用方负责网络与授权,组件负责生命周期。
(node: TreeNode<T>, context: { readonly cursor: string | null; readonly signal: AbortSignal; readonly reason: TreeLoadReason; }) => Promise<TreeChildrenPage<T>>TreeLoadReason
分支请求的触发场景。
"expand" | "more" | "retry" | "reload"TreeNode
数据驱动节点;key 全树唯一,value 不承担身份。
TreeNode<T>| 属性 | 类型 | 可选 | 默认值 / 证据 | 说明 | 来源 |
|---|---|---|---|---|---|
| key | string | 否 | 未声明;见说明/约束 | 稳定非空标识。 | headless: @selrux/headless/dist/types/components/tree/contracts/node.d.ts |
| name | string | 否 | 未声明;见说明/约束 | 展示与可访问名称。 | headless: @selrux/headless/dist/types/components/tree/contracts/node.d.ts |
| value | string | number | 否 | 未声明;见说明/约束 | 可搜索的业务值,允许重复。 | headless: @selrux/headless/dist/types/components/tree/contracts/node.d.ts |
| isLeaf | boolean | 是 | 未声明;见说明/约束 | false 表示尚可异步展开;true 必须没有子项。 | headless: @selrux/headless/dist/types/components/tree/contracts/node.d.ts |
| childrenState | "unloaded" | "partial" | "complete" | 是 | 未声明;见说明/约束 | 已知子项的完整性。 | headless: @selrux/headless/dist/types/components/tree/contracts/node.d.ts |
| nextCursor | string | 是 | 未声明;见说明/约束 | 部分加载的下一页游标。 | headless: @selrux/headless/dist/types/components/tree/contracts/node.d.ts |
| disabled | boolean | 是 | 未声明;见说明/约束 | 禁止当前节点交互,阻断祖先级联。 | headless: @selrux/headless/dist/types/components/tree/contracts/node.d.ts |
| selectable | boolean | 是 | 未声明;见说明/约束 | 是否允许行选择。 | headless: @selrux/headless/dist/types/components/tree/contracts/node.d.ts |
| checkable | boolean | 是 | 未声明;见说明/约束 | false 隐藏自身复选但级联可穿透。 | headless: @selrux/headless/dist/types/components/tree/contracts/node.d.ts |
| disableCheckbox | boolean | 是 | 未声明;见说明/约束 | 禁用复选并隔离级联。 | headless: @selrux/headless/dist/types/components/tree/contracts/node.d.ts |
| searchData | Readonly<Record<string, string | readonly string[]>> | 是 | 未声明;见说明/约束 | 不自动渲染的搜索文档。 | headless: @selrux/headless/dist/types/components/tree/contracts/node.d.ts |
| data | T | 是 | 未声明;见说明/约束 | 业务原始数据。 | headless: @selrux/headless/dist/types/components/tree/contracts/node.d.ts |
| children | readonly TreeNode<T>[] | 是 | 未声明;见说明/约束 | 已知直接子项。 | headless: @selrux/headless/dist/types/components/tree/contracts/node.d.ts |
其余 0 个 React 原生属性按继承汇总;关键原生属性已展开。
TreeNodeRenderContext
用户渲染得到默认内容,保留原交互壳。
TreeNodeRenderContext| 属性 | 类型 | 可选 | 默认值 / 证据 | 说明 | 来源 |
|---|---|---|---|---|---|
| defaultNode | ReactNode | 否 | 未声明;见说明/约束 | ui: @selrux/ui/dist/types/components/tree/tree-props.d.ts | |
| depth | number | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/primitives/context-types.d.ts | |
| expanded | boolean | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/primitives/context-types.d.ts | |
| selected | boolean | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/primitives/context-types.d.ts | |
| checked | boolean | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/primitives/context-types.d.ts | |
| mixed | boolean | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/primitives/context-types.d.ts | |
| loading | boolean | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/primitives/context-types.d.ts | |
| matched | boolean | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/primitives/context-types.d.ts | |
| active | boolean | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/primitives/context-types.d.ts | |
| checkDisabled | boolean | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/primitives/context-types.d.ts |
其余 0 个 React 原生属性按继承汇总;关键原生属性已展开。
TreePathContext
祖先路径按需读取,避免常驻每个节点的完整路径副本。
TreePathContext<T>| 属性 | 类型 | 可选 | 默认值 / 证据 | 说明 | 来源 |
|---|---|---|---|---|---|
| pathNames | () => readonly string[] | 否 | 未声明;见说明/约束 | 不包含当前节点的祖先名称。 | headless: @selrux/headless/dist/types/components/tree/contracts/node.d.ts |
| ancestors | () => readonly TreeNode<T>[] | 否 | 未声明;见说明/约束 | 不包含当前节点的祖先数据。 | headless: @selrux/headless/dist/types/components/tree/contracts/node.d.ts |
其余 0 个 React 原生属性按继承汇总;关键原生属性已展开。
TreeProps
可搜索的树:支持虚拟化、连接线、自定义内容与异步勾选。
TreeProps<T>| 属性 | 类型 | 可选 | 默认值 / 证据 | 说明 | 来源 |
|---|---|---|---|---|---|
| data | readonly TreeNode<T>[] | 否 | 未声明;见说明/约束 | 不可变数据基线;引用变化重置加载代次。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| showLine | boolean | 是 | 未声明;见说明/约束 | 默认开启连接线,关闭后保持缩进。 | ui: @selrux/ui/dist/types/components/tree/tree-props.d.ts |
| size | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | 是 | md(继承配置域尺寸,默认 md。) | 继承配置域尺寸,默认 md。 | ui: @selrux/ui/dist/types/components/tree/tree-props.d.ts |
| renderNode | ((node: TreeNode<T>, context: TreeNodeRenderContext) => ReactNode) | 是 | 未声明;见说明/约束 | 默认展示 name,可替换内容但不能覆盖 role 或焦点。 | ui: @selrux/ui/dist/types/components/tree/tree-props.d.ts |
| renderIcon | ((node: TreeNode<T>, context: TreeRenderContext) => ReactNode) | 是 | 未声明;见说明/约束 | 装饰图标,不承担展开动作。 | ui: @selrux/ui/dist/types/components/tree/tree-props.d.ts |
| classNames | Partial<Record<TreeSemanticSlot, string>> | 是 | 未声明;见说明/约束 | 语义 class 覆盖。 | ui: @selrux/ui/dist/types/components/tree/tree-props.d.ts |
| styles | Partial<Record<TreeSemanticSlot, CSSProperties>> | 是 | 未声明;见说明/约束 | 语义内联样式覆盖。 | ui: @selrux/ui/dist/types/components/tree/tree-props.d.ts |
| emptyText | string | 是 | 未声明;见说明/约束 | 空数据文案覆盖。 | ui: @selrux/ui/dist/types/components/tree/tree-props.d.ts |
| noMatchText | string | 是 | 未声明;见说明/约束 | 零匹配文案覆盖。 | ui: @selrux/ui/dist/types/components/tree/tree-props.d.ts |
| loadingText | string | 是 | 未声明;见说明/约束 | 搜索/加载中的文案覆盖。 | ui: @selrux/ui/dist/types/components/tree/tree-props.d.ts |
| className | string | 是 | 未声明;见说明/约束 | react-native: @types/react/index.d.ts | |
| aria-describedby | string | 是 | 未声明;见说明/约束 | Identifies the element (or elements) that describes the object. | react-native: @types/react/index.d.ts |
| aria-label | string | 是 | 未声明;见说明/约束 | Defines a string value that labels the current element. | react-native: @types/react/index.d.ts |
| onClick | MouseEventHandler<HTMLDivElement> | 是 | 未声明;见说明/约束 | react-native: @types/react/index.d.ts | |
| dataVersion | string | number | 是 | 未声明;见说明/约束 | 业务数据源重置标记。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| disabled | boolean | 是 | 未声明;见说明/约束 | 禁止用户操作。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| invalid | boolean | 是 | 未声明;见说明/约束 | 错误语义。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| expandedKeys | readonly string[] | 是 | 未声明;见说明/约束 | 受控用户展开集合。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| defaultExpandedKeys | readonly string[] | 是 | 未声明;见说明/约束 | 初始展开集合。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| defaultExpandDepth | number | 是 | 未声明;见说明/约束 | 初始展开层数,不自动请求。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| onExpandedChange | ((keys: readonly string[], details: TreeExpandedDetails) => void) | 是 | 未声明;见说明/约束 | 展开提议。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| selectionMode | "none" | "single" | "multiple" | 是 | 未声明;见说明/约束 | 行选择与复选独立。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| selectedKeys | readonly string[] | 是 | 未声明;见说明/约束 | 受控行选择。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| defaultSelectedKeys | readonly string[] | 是 | 未声明;见说明/约束 | 初始行选择。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| onSelectionChange | ((keys: readonly string[], details: TreeSelectionDetails) => void) | 是 | 未声明;见说明/约束 | 行选择提议。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| checkable | boolean | 是 | 未声明;见说明/约束 | 显示复选能力。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| checkStrictly | boolean | 是 | 未声明;见说明/约束 | 独立复选,不向父子传导。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| checkedState | TreeCheckedState | 是 | 未声明;见说明/约束 | 受控包含/排除规则。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| defaultCheckedState | TreeCheckedState | 是 | 未声明;见说明/约束 | 初始复选规则。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| onCheckedChange | ((state: TreeCheckedState, details: TreeCheckedDetails) => void) | 是 | 未声明;见说明/约束 | 用户复选提议,加载完成不触发。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| filterable | boolean | 是 | 未声明;见说明/约束 | UI 可据此组合搜索框。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| searchValue | string | 是 | 未声明;见说明/约束 | 受控查询,输入即时回调,计算延迟合并。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| defaultSearchValue | string | 是 | 未声明;见说明/约束 | 初始查询。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| onSearch | ((query: string) => void) | 是 | 未声明;见说明/约束 | 搜索值提议。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| searchMode | "filter" | "highlight" | 是 | 未声明;见说明/约束 | 过滤或仅标记当前视图。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| remote | boolean | 是 | 未声明;见说明/约束 | 由外部提供搜索快照。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| searchResult | TreeSearchResult<T> | 是 | 未声明;见说明/约束 | 外部带代次的搜索结果。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| loadChildren | TreeLoadChildren<T> | 是 | 未声明;见说明/约束 | 网络请求适配。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| loadConcurrency | number | 是 | 4(并发上限,默认 4。) | 并发上限,默认 4。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| loadTimeout | number | 是 | 30000(请求超时毫秒,默认 30000。) | 请求超时毫秒,默认 30000。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| onLoadError | ((error: Error, details: TreeErrorDetails) => void) | 是 | 未声明;见说明/约束 | 分支错误观察。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| onDataError | ((error: Error, details: TreeErrorDetails) => void) | 是 | 未声明;见说明/约束 | 数据/搜索错误观察。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| virtual | boolean | 是 | true(固定行高虚拟化,默认 true。) | 固定行高虚拟化,默认 true。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| itemSize | number | 是 | 32(固定行高,默认 32。) | 固定行高,默认 32。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| height | number | 是 | 320(视口高度,默认 320。) | 视口高度,默认 320。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| overscan | number | 是 | 6(额外窗口行,默认 6。) | 额外窗口行,默认 6。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| onContentScroll | ((details: VirtualListScrollDetails) => void) | 是 | 未声明;见说明/约束 | 滚动几何变化。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| apiRef | Ref<TreeApi<T>> | 是 | 未声明;见说明/约束 | 实例动作,与 DOM ref 分离。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| ref | Ref<HTMLDivElement> | 是 | 未声明;见说明/约束 | 根 DOM。 | headless: @selrux/headless/dist/types/components/tree/contracts/props.d.ts |
| searchFields | readonly string[] | 是 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/search/search-types.d.ts | |
| getSearchData | ((node: TreeNode<T>, context: TreePathContext<T>) => TreeSearchData) | 是 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/search/search-types.d.ts | |
| filterNode | ((query: string, node: TreeNode<T>, context: TreePathContext<T>) => boolean) | 是 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/search/search-types.d.ts |
其余 272 个 React 原生属性按继承汇总;关键原生属性已展开。
TreeRenderContext
内容渲染只能接触状态,不能替换交互壳。
TreeRenderContext| 属性 | 类型 | 可选 | 默认值 / 证据 | 说明 | 来源 |
|---|---|---|---|---|---|
| depth | number | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/primitives/context-types.d.ts | |
| expanded | boolean | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/primitives/context-types.d.ts | |
| selected | boolean | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/primitives/context-types.d.ts | |
| checked | boolean | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/primitives/context-types.d.ts | |
| mixed | boolean | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/primitives/context-types.d.ts | |
| loading | boolean | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/primitives/context-types.d.ts | |
| matched | boolean | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/primitives/context-types.d.ts | |
| active | boolean | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/primitives/context-types.d.ts | |
| checkDisabled | boolean | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/primitives/context-types.d.ts |
其余 0 个 React 原生属性按继承汇总;关键原生属性已展开。
TreeSearchData
Tree 的节点身份、业务数据与派生搜索字段。
{ readonly [x: string]: string | readonly string[]; }TreeSearchResult
外部搜索快照,必须与当前 query 和最新 revision 一致。
TreeSearchResult<T>| 属性 | 类型 | 可选 | 默认值 / 证据 | 说明 | 来源 |
|---|---|---|---|---|---|
| query | string | 否 | 未声明;见说明/约束 | 对应的原始查询。 | headless: @selrux/headless/dist/types/components/tree/contracts/loading.d.ts |
| revision | number | 否 | 未声明;见说明/约束 | 同一查询的单调递增版本。 | headless: @selrux/headless/dist/types/components/tree/contracts/loading.d.ts |
| status | "loading" | "error" | "success" | 否 | 未声明;见说明/约束 | 查询状态。 | headless: @selrux/headless/dist/types/components/tree/contracts/loading.d.ts |
| nodes | readonly TreeNode<T>[] | 否 | 未声明;见说明/约束 | 包含祖先上下文的结果树。 | headless: @selrux/headless/dist/types/components/tree/contracts/loading.d.ts |
| matchedKeys | readonly string[] | 否 | 未声明;见说明/约束 | 真正命中的 key,不含仅作上下文的祖先。 | headless: @selrux/headless/dist/types/components/tree/contracts/loading.d.ts |
| complete | boolean | 否 | 未声明;见说明/约束 | 查询是否完整。 | headless: @selrux/headless/dist/types/components/tree/contracts/loading.d.ts |
| nextCursor | null | string | 是 | 未声明;见说明/约束 | 外部后续页游标。 | headless: @selrux/headless/dist/types/components/tree/contracts/loading.d.ts |
| error | Error | 是 | 未声明;见说明/约束 | 可呈现的失败信息。 | headless: @selrux/headless/dist/types/components/tree/contracts/loading.d.ts |
其余 0 个 React 原生属性按继承汇总;关键原生属性已展开。
TreeSelectionDetails
行选择差异。
TreeSelectionDetails| 属性 | 类型 | 可选 | 默认值 / 证据 | 说明 | 来源 |
|---|---|---|---|---|---|
| addedKeys | readonly string[] | 否 | 未声明;见说明/约束 | 新增节点。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
| removedKeys | readonly string[] | 否 | 未声明;见说明/约束 | 移除节点。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
| key | string | 否 | 未声明;见说明/约束 | 触发节点。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
| reason | "pointer" | "keyboard" | "api" | 否 | 未声明;见说明/约束 | 操作来源。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
| originalEvent | Event | 是 | 未声明;见说明/约束 | 原始 DOM 事件。 | headless: @selrux/headless/dist/types/components/tree/contracts/selection.d.ts |
其余 0 个 React 原生属性按继承汇总;关键原生属性已展开。
TreeSemanticSlot
可覆盖的语义外观槽。
"content" | "search" | "status" | "root" | "viewport" | "item" | "switcher" | "checkIndicator" | "icon" | "line" | "empty" | "loading" | "error"TreeSize
六档尺寸沿用库内控件比例。
"xs" | "sm" | "md" | "lg" | "xl" | "2xl"TreeSnapshot
可序列化的已加载状态快照。
TreeSnapshot<T>| 属性 | 类型 | 可选 | 默认值 / 证据 | 说明 | 来源 |
|---|---|---|---|---|---|
| data | readonly TreeNode<T>[] | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/contracts/api.d.ts | |
| searchValue | string | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/contracts/api.d.ts | |
| expandedKeys | readonly string[] | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/contracts/api.d.ts | |
| selectedKeys | readonly string[] | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/contracts/api.d.ts | |
| checkedState | TreeCheckedState | 否 | 未声明;见说明/约束 | headless: @selrux/headless/dist/types/components/tree/contracts/api.d.ts |
其余 0 个 React 原生属性按继承汇总;关键原生属性已展开。
节点数据约束
name 是非空展示文本及可访问名称;value 可重复,搜索默认转换为字符串。searchData 只参与已启用字段的搜索,data 原样留给业务渲染。完整字段由公开 TreeNode 声明生成。
key 不使用路径名称、数组下标或 value 的隐式字符串转换生成。这样允许节点改名、移动及 value 重复,也不会混淆数字 1 与字符串 "1"。选择和展开回调均使用 key,业务 value 通过解析后的节点获取。
省略状态时:有 children(包括空数组)视为完整;无 children 且 isLeaf=false 为未加载;其他情况视为叶子。异步空分支必须明确 isLeaf=false,加载返回空且完整后转为叶子。partial 必须有 nextCursor,complete 不得附 nextCursor,isLeaf=true 不得同时有子项或不完整状态。根级分页由应用负责传入 data,不冒充节点子页。
重复 key、循环引用、多个父节点引用同一 key、非法字段与状态冲突按数据错误处理。错误指出冲突 key,生产同样拒绝有问题的数据版本/加载页;保留上一份合法快照,不静默去重或挂接到错误父级。初次数据非法显示错误态并禁用数据操作。
异步加载与远程快照
loadChildren(node, { cursor, signal, reason }) 返回 { nodes, nextCursor };第一页 cursor=null,终页 nextCursor=null。reason 是 expand/more/retry/reload;把 signal 传给实际网络请求。默认并发 4、超时 30000ms,加载/更多/重试位于父行尾部,不占业务节点编号。
每个父级仅一个在途请求,标识为 dataGeneration + parentKey + cursor + requestId。分页只按游标顺序追加;重试同页不重复提交,重复/冲突 key 使整页失败。空页且还有游标允许继续手动加载,但游标重复或循环必须报错,不自动无限翻页。
折叠取消尚未开始的排队请求;在途请求默认允许完成缓存,不自动重新展开。删除、刷新或新数据代次取消在途请求;即使 loader 无视 signal,旧结果也不能提交。队列上限 32,超限分支保持未加载并给出可重试状态,不留下永久 loading。
加载状态为 idle/queued/loading/partial/loaded/error,错误不清空已成功子页,不自动重试。reloadNode 中止当前请求后请求第一页,成功后原子替换当前子树,失败保留旧数据并显示重试按钮。缓存只含当前数据代次已加载分支,不做后台 TTL 自动刷新。
远程搜索 TreeSearchResult<T> 包含 query、revision、status(loading/success/error)、nodes(保留祖先路径的结果树)、matchedKeys、complete、nextCursor、error。只提交 query 与当前输入一致且 revision 最新的结果;父级负责取消请求、分页和错误重试。搜索快照与基础树隔离,clear 后恢复基础树;相同 key 的身份必须一致。远程搜索上下文中的父节点禁止级联勾选;strict 模式独立勾选具体节点(包括调用方提供的上下文节点)。首版不在远程搜索快照里调用 loadChildren,避免混入非查询结果。
实例动作
UI 使用单独 apiRef,保留 ref 指向根 DOM 的库内习惯。TreeApi 提供:
scrollToKey(key, {align}):仅定位当前可见 key,返回 visible/not-visible/not-found;不隐式展开或发请求。revealKey(key, {focus}):仅对已知祖先路径提出展开请求,提交后定位;受控父级未接受时返回 pending;未知路径需消费方先加载,不能递归全树查找。reloadNode(key)/retryLoad(key):明确的分支刷新/失败重试入口。resolveChecked(options):显式枚举勾选结果;枚举成本为 O(N),只在明确提交动作调用。getSnapshot():返回查询、展开、行选择、复选意图与已加载结构副本,不允许篡改内部集合。getSnapshot 会遍历已加载数据,只在保存等明确动作调用。
不自动注入十万个隐藏 input。原生 form reset、required 与提交序列化由应用表单适配;组件提供受控状态与 invalid/aria-describedby 透传。首版不宣称与原生 select 等价。
虚拟化与自定义内容
默认 virtual=true、height=320、overscan=6。Headless 默认行高 32px,UI 六档尺寸对应 24/28/32/36/40/48px。虚拟模式所有行必须同高,itemSize 应覆盖自定义内容高度;小数据自然多行可用 virtual=false 并设置 styles.content.whiteSpace='normal'。非虚拟模式不适用于十万节点。
renderNode 只替换内容,context.defaultNode 保留名称高亮;上下文包含深度、展开、选择、勾选、半选、加载、命中、活动及复选禁用状态。渲染槽不改变 name 的可访问名称;交互内容的边界见自定义渲染契约。
classNames/styles 提供 root、search、status、viewport、item、switcher、checkIndicator、icon、content、line、empty、loading、error 槽。开启连接线时使用方框加减号,叶子短横线从本级竖线接出,末项折线收口,祖先续线贯穿多级后代;关闭 showLine 改用箭头并保留缩进。自然多行以第一行对齐图标与短横线。
十万节点示例按按钮生成,不在打开页面时分配。虚拟化减少 DOM,不消除搜索、级联汇总和导出的遍历成本;长路径增加索引内存。内置字符预算超限通过 onDataError 报错,可减少字段、使用短别名或远程搜索。本批不重新证明十万节点的性能、内存峰值或全量性能门槛。
自定义渲染边界
renderNode 不能覆盖 role、id、ARIA、tabIndex 或焦点壳;默认仅非交互内容。额外按钮/菜单需要 Headless 组合与单独键盘设计,不以 stopPropagation 冒充完整可访问性。节点 name 始终是可访问名称,value 和隐藏 searchData 不自动读出。
键盘与无障碍
为每棵树提供 aria-label 或 aria-labelledby;placeholder 不替代可访问名称。焦点、行选择、复选分别通过 aria-activedescendant、aria-selected、aria-checked 表达。虚拟窗口额外挂载活动行,保证焦点目标存在;连接线不进入可访问树。
| 按键 | 行为 |
|---|---|
| Tab / Shift+Tab | 搜索框、树容器与外部控件间移动,不逐节点 Tab |
| ↑ / ↓、Home / End | 前后或首尾可见项,不自动选择 |
| → / ← | 展开或进入子项,收起或返回父项;RTL 镜像方向 |
| Enter | 行选择;selectionMode=none 时切换展开 |
| Space | checkable 时勾选,否则行选择;不可勾选行不回退选择 |
| Shift+点击 / Shift+Space | multiple 行选择扩展当前可见范围;启用复选时 Space 优先复选 |
| 名称前缀 | 按 name 定位,不查隐藏字段 |
| Escape / Alt+Enter | 搜索框 Escape 清空;树内 Alt+Enter 进入父行分页/重试,Escape 返回 |
自动化键盘与 DOM 语义检查不代表人工读屏兼容已验收;VoiceOver/Safari 与 NVDA/Chromium 尚未完成本批验证。
文档快照:edbed4e3949112ae4797ba611a523984