Tree 树
用于展示层级数据,支持展开/收起、选中、级联勾选、点选多选、搜索过滤、懒加载、键盘操作与节点拖拽。
⚠️ 破坏性变更(v2.5):
expanded/checked由「逗号分隔字符串」改为「JSON 字符串数组」。 旧写法expanded="a,b"/checked="a-1,b"已失效,请迁移为expanded='["a","b"]'/checked='["a-1","b"]'。 迁移原因:key 本身含逗号时逗号串会解析错误;JSON 数组与oas-tree-select的expanded/value形态统一。 若 key 可能含逗号等特殊字符,旧版数据会丢节点,升级后请按数组形态重建属性。
基础用法
层级树
点击展开按钮显示 / 收起子节点,点击节点文本选中该节点;树支持完整键盘操作(↑/↓ 移动焦点、→ 展开、← 收起、Home/End、Space 勾选、Enter 选中)。
触屏适配:展开按钮图标保持 20px,触控(coarse pointer)下命中区自动扩到 44px 触控目标(透明热区外扩),点中率与视觉密度兼顾。
受控展开与选中
初始展开与选中
expanded 为 JSON 字符串数组(如 '["a","b"]'),selected 为选中节点 key。也可组合 default-expand-all(首次全展开,显式 expanded 优先)、auto-expand-parent(外部注入深层 key 时自动补全祖先)、expand-trigger="node"(点击节点即展开/收起)。
勾选(级联)
勾选级联(父选全勾、半选回显)
勾选集合(checked 属性,JSON 数组):—
checkable 开启勾选后为级联模型(与 oas-tree-select 语义一致):勾选父级自动勾选其全部可勾选子级;某父级的全部子级被勾选后父级自动收敛为勾选;部分子级勾选时父级复选框显示半选(indeterminate)。
非级联勾选(check-strictly)与默认展开
check-strictly 关闭级联(勾选父级不影响子级);default-expand-all 初始全展开;auto-expand-parent 宿主写入 expanded 属性时自动补全祖先展开(勾选/点选不触发)。
空态(empty 文案与空态插槽)
empty 属性自定义空态文案;也可用 template[slot="empty"] 放富内容。
check-strategy:all(默认,父级+子级全进值)/parent(子级全选时以父级代表,只保留父级)/child(只保留叶子);check-strictly:父子解耦,勾选互不级联、无半选;- 数据字段可加
disableCheckbox: true禁单个节点勾选(级联跳过);整树禁交互用组件级disabled属性。
点选多选
点选多选(multiple,再点取消)
设置 multiple 后 selected 变为 JSON 字符串数组,点击标签在集合中追加 / 移除(再点已选项取消)。勾选(checkable)与点选(multiple/selected)是两套独立模型,可同时启用。
展开行为
手风琴(accordion)+ 树线(tree-lines)+ 点击节点展开
accordion:展开某节点时自动收起同层兄弟(手风琴互斥);tree-lines:渲染祖辈缩进引导线(属性名与oas-tree-select一致);expand-trigger="node":点击节点文本同时展开/收起(缺省"toggle"只点箭头);auto-expand-parent:宿主setAttribute('expanded', '["深层key"]')时组件自动补全祖先展开。
搜索过滤
树内过滤(命中保留祖先与子树 + 可选高亮)
filter 为搜索词(属性驱动,搜索框由宿主自配,示例用 oas-input 联动)。命中后保留其全部祖先(路径)与全部后代(命中即含子树),不依赖展开状态;无命中显示空态。filter-highlight 开启时默认 label 文本命中片段包 <mark> 高亮;也可用属性回调 filterNode(label, node) 自定义命中判定(缺省 label 包含关键词,大小写不敏感)。
字段映射
字段别名(field-names)
宿主数据结构不同时用 field-names 映射(JSON 对象,键:key/label/children/disabled/isLeaf/loaded,值对应数据里的字段名),在数据入口归一化一次,与 oas-tree-select 共用同一套字段归一。
禁用状态
节点禁用(disabled / selectable / disableCheckbox)
- 节点
disabled: true:整行不可交互(点选/展开/勾选); - 节点
selectable: false:点选与键盘选中被排除,勾选与展开不受影响; - 节点
disableCheckbox: true:复选框禁用且不进级联; - 组件级
disabled属性:整树禁交互(只读展示树)。
命令式方法与滚动
全部展开 / 收起 / 定位
命令式方法(数据仍由宿主受控,方法只换算展开集合 / 滚动位置):
expandAll()/collapseAll():全部展开 / 全部收起;expand(keys: string[])/collapse(keys: string[]):展开 / 收起指定 key 集合;scrollTo(key, { expand?: boolean }):滚动定位到节点(默认先展开祖先链;expand: false时不改展开状态)。
懒加载
懒加载(展开时异步回填子节点)
点击「目录 A」前的展开箭头触发加载
懒加载失败重试(oas-load-error)
点「会失败」的展开箭头看失败事件与重试
设置 lazy 后,无 children 且未标记 isLeaf / loaded 的节点视为「未加载」:点击展开箭头派发 oas-load(detail: { key })并调用 load 属性回调,由宿主回填子节点后重设 data 属性;加载期间展开箭头位置显示 loading 占位(可 template[slot="toggle-loading"] 替换),回填完成后自动展开并收起占位。load 回调返回 Promise 且 reject 时:自动清除加载态、回滚展开、派发 oas-load-error(detail: { key, error }),节点恢复为可再次点击重试。标记 isLeaf: true 的节点不显示展开箭头。
节点拖拽
可拖拽(拖动换序 / 换父)
拖拽节点到目标行上 / 下 / 中部,分别插入其前 / 后 / 子
设置 draggable 后可拖拽节点换序或换父:拖到目标行上 25% 区域插入其前(before)、下 25% 区域插入其后(after)、中部且目标可展开时移入其下(inner;目标不可展开时中部按上下半行取 before/after),拖拽过程有插入线与高亮反馈;松手派发 oas-node-drop(detail: { dragKey, dropKey, position }),由宿主更新数据后重设 data 属性。拖到树空白处视为移入根(dropKey 为空字符串、position: 'inner')。
拖拽全程另有生命周期事件组:oas-node-dragstart(detail: { dragKey })、oas-node-dragover / oas-node-dragleave(detail: { dragKey, dropKey, position },拖到空白处 dropKey 为空、position: 'inner')、oas-node-dragend(detail: { dragKey }),可用于自定义拖拽提示、跨树联动等场景。
落点合法性可用属性回调守卫(拖拽中即拒绝,无插入线反馈):
tree.allowDrop = ({ dragKey, dropKey, position }) => dropKey !== 'grp-1' // 不允许拖入该节点
tree.allowDrag = (node) => node.key !== 'item-1' // 该节点不可被拖动大数据量(虚拟滚动)
万级节点虚拟滚动
设置 height 开启虚拟化(搭配 row-height 定高):树复用 oas-virtual-list 只渲染可见窗口内的节点,展开状态保存在 expanded 属性中,滚动与重渲染均不丢失;键盘导航与 scrollTo() 会联动滚动窗口。
自定义节点渲染
自定义节点(图标 + 富文本)
节点内容可用 template[slot="node"] 提供静态骨架([data-node-label] 节点自动绑定节点 label),template[slot="toggle"] 可替换默认展开箭头;每个节点行渲染后派发 oas-node-render(detail: { node, element, level, expanded, selected, checked }),宿主可监听改写 element 为任意图标 / 富文本。示例中任务数徽标即由该事件写入;键盘与 ARIA(treeitem / aria-expanded / aria-level)在自定义渲染下保持不变。
目录模式(文件浏览器)
目录模式(文件浏览器样式)
设置 directory 后按文件浏览器风格渲染:有 children(或懒加载下未加载)的节点显示文件夹图标,isLeaf / 无 children 的节点显示文件图标;文件夹按展开 / 收起切换图标,层级缩进与 hover 高亮行沿用行样式。可叠加 tree-lines 显示祖辈引导线。
节点重命名
内联重命名(双击或 F2,Enter 提交 / Esc 取消)
双击「研发团队」或其子节点 label,或选中后按 F2 重命名
设置 can-rename 开启节点重命名:双击节点 label(或选中后按 F2)进入内联编辑态;Enter / 失焦提交、Esc 取消(还原旧值、不派发事件)。编辑态输入框内方向键归输入框,不影响树 roving 键盘导航;节点数据可加 renamable: false 细粒度禁止单个节点重命名。
数据由宿主受控:提交时组件只派发 oas-node-rename(detail: { key, label, oldLabel })不改数据——宿主监听该事件把新 label 写回数据并重设 data 属性后,行内才显示新名字;宿主不更新则保持旧值(避免组件单方面改数据导致不同步)。
展开/收起过渡动画
展开收起过渡(motion 开关对比)
设置 motion 开启展开/收起的高度过渡动画(默认关):展开时新增子行从 0 高平滑生长到自然行高,收起时子行先收缩离场再移除,时长/缓动走 --oas-transition-* token。虚拟滚动模式(设置 height)下展开入场降级为淡入、收起即时切换——虚拟列表行高定值不适合高度动画,避免错位与性能损耗;动画尊重 prefers-reduced-motion(系统减少动效时自动停用)。
展开/收起事件
oas-expand(节点展开/收起)
最近动作:点击展开箭头试试
任意展开/收起交互(展开箭头、expand-trigger="node"、键盘 →/←)都会派发 oas-expand,detail: { key, expanded, node }——node 为该数据节点的快照,宿主可据此联动其他视图。
事件
选中与勾选事件
选中:— · 勾选:—
尺寸五档(size)
size 控制整树字号与行内边距,五档:xs / small / medium / large / xl(sm / md / lg 别名等价接受,非法值回落 medium)。medium 为默认档(与不设置一致)。
size 五档对比
整行块级选中区(block-node)
block-node 把行渲染为更高的块级命中区:选中/hover 色带本就整行覆盖,开启后行块再加高一档,适合触达密集(触屏、频繁点选)的场景。默认关闭(紧凑行)。
block-node 开关对比
整树点选开关(selectable)
selectable 控制整树行点选(默认开启保持现状);设为 "false" 后点击/键盘不再选中、不派发 oas-select,展开与勾选不受影响。节点数据级的 selectable: false 字段仍可细粒度排除单节点。
selectable 开关
整树全选(check-all)
check-all(配 checkable 生效)在树顶部渲染整树全选项行:全选写入全部可勾选节点,部分勾选时复选框呈半选(indeterminate),再次点选取消全选;disabled / disableCheckbox 节点不参与。文案默认「全选」,可用 check-all-label 覆盖。每次切换派发 oas-check-all(detail: { checked, values })。
check-all 整树全选
勾选顶部「全选」或逐项勾选,观察三态;再点一次取消全选。
API
oas-tree
属性
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
accordion | 手风琴(同级同时只展开一支) | boolean | — |
auto-expand-parent | 勾选子节点时自动展开其父级 | boolean | — |
block-node | 整行块级选中/hover 区(行块加高一档) | boolean | — |
can-rename | 节点重命名总开关:开启后双击节点 label 或按 F2 进入内联编辑,Enter 提交 / Esc 取消 / 失焦提交;提交派发 oas-node-rename(节点数据可加 renamable: false 细粒度禁单个节点) | boolean | — |
check-all | 顶部整树全选项行(三态 indeterminate;需 checkable) | boolean | — |
check-all-label | 全选项行文案(缺省复用 i18n 全选) | string | — |
check-strategy | 勾选导出策略:all(默认)/ parent / child(checkable 级联时生效) | string | all |
check-strictly | 勾选父子解联(勾选父级不联动子级) | boolean | — |
checkable | 是否显示复选框 | boolean | — |
checked | 勾选节点 key 集合(JSON 字符串数组,如 '["a"]';v2.5 前的旧逗号串已废弃,解析失败按空集合回落并告警) | string | — |
data | 节点数据 [{ key, label, children?, disabled?, isLeaf?, loaded?, renamable? }],JSON 字符串 | TreeNode[] | string | [] |
default-expand-all | 默认展开全部节点(expanded 属性缺席时生效) | boolean | — |
directory | 目录模式:有 children(或懒加载下未加载)的节点显示文件夹图标,isLeaf / 无 children 的节点显示文件图标,文件夹按展开 / 收起切换图标 | boolean | — |
disabled | 整树禁用(点选/勾选/展开/拖拽全停,浏览保留) | boolean | — |
draggable | 节点可拖拽换序 / 换父,落点显示插入线 / 高亮,松手派发 oas-node-drop | boolean | — |
empty | 空态文案(无数据时;无匹配时走 locale 无匹配文案) | string | — |
expand-trigger | 节点展开触发:toggle(默认,仅箭头)/ node(点节点行展开) | string | toggle |
expanded | 展开节点 key 集合(JSON 字符串数组,如 '["a"]';v2.5 前的旧逗号串已废弃,解析失败按空集合回落并告警) | string | — |
field-names | 字段别名 JSON(如 {"label":"name","value":"id","children":"subs"};原始数据不拷贝映射,node-render 拿到宿主原对象) | string | — |
filter | 树内搜索过滤(输入关键词;配 filter-highlight 高亮与 el.filterNode 自定义) | string | — |
filter-highlight | 搜索命中片段高亮(mark 标记) | boolean | — |
height | 虚拟滚动视口高度(px);设置后开启大数据量虚拟化渲染 | string | — |
lazy | 懒加载:无 children 且未标记 isLeaf / loaded 的节点,展开时触发加载 | boolean | — |
motion | 展开/收起高度过渡动画(默认关):非虚拟模式行容器 max-height 过渡展开/收起,虚拟滚动模式入场降级为淡入、收起即时;时长/缓动走 --oas-transition-*,prefers-reduced-motion 下停用 | boolean | — |
multiple | 点选多选(Ctrl/⌘ 点击多选;勾选集 selected 为 JSON 数组) | boolean | — |
row-height | 虚拟化时每行固定高度(px) | string | 32 |
selectable | 整树点选开关,"false" 时点击/键盘不选中不派发 oas-select(展开/勾选不受影响) | string | true |
selected | 选中节点 key | string | — |
size | 整树字号与行距五档(xs~xl,别名等价,非法回落 medium) | string | medium |
tree-lines | 树线缩进引导线 | boolean | — |
Property(JS property;是否写回 attribute 见各行说明)
| Property | 说明 | 类型 | 默认值 |
|---|---|---|---|
load | 懒加载函数(property 通道,(node) => Promise<children>) | (payload: { key: string }) => void | Promise<unknown> | — |
事件
| 事件 | 说明 |
|---|---|
oas-check | 勾选变化,detail: { key, checked } |
oas-check-all | 全选行切换时派发,detail: { checked, values } |
oas-expand | 节点展开/收起时派发,detail: { key, expanded, node }(node 为数据节点快照) |
oas-load | 懒加载触发,detail: { key };宿主回填 children 后重设 data 属性 |
oas-load-error | 懒加载失败时派发,detail: { key, error },error 为错误消息字符串(loading 消失可再点重试) |
oas-node-dragend | 拖拽结束时派发,detail: { dragKey } |
oas-node-dragleave | 拖拽离开目标时派发,detail: { dragKey, dropKey, position } |
oas-node-dragover | 拖拽悬过目标时派发,detail: { dragKey, dropKey, position }(空白处 dropKey 为空、position 为 inner) |
oas-node-dragstart | 拖拽开始时派发,detail: { dragKey } |
oas-node-drop | 节点拖放,detail: { dragKey, dropKey, position },position 为 before / after / inner;dropKey 为空字符串表示移入根 |
oas-node-rename | 内联重命名提交(Enter / 失焦),detail: { key, label, oldLabel };数据由宿主受控——组件不改数据模型,宿主监听后更新 data 才生效(不更新则保持旧值;Esc 取消不派发) |
oas-node-render | 每个渲染的节点行派发,detail: { node, element, level, expanded, selected, checked }(element 为节点 label 容器,宿主可改写为图标 / 富文本) |
oas-select | 选中节点,detail: { key, selected } |
插槽
| 名称 | 说明 |
|---|---|
template[slot="empty"] | 自定义空态内容 |
template[slot="node"] | 节点行静态模板,克隆到每个节点 label 容器;[data-node-label] 节点自动绑定节点 label |
template[slot="toggle"] | 展开按钮静态模板,克隆到每个可展开节点的展开按钮内(替换默认 › 图标) |
template[slot="toggle-loading"] | 懒加载展开中的指示器(替换 spinner) |
节点字段说明:
isLeaf: true表示显式叶子(懒加载下不显示展开箭头);loaded: true表示已加载完成(配合children使用,避免重复触发加载);renamable: false表示该节点不可重命名(配合can-rename,缺省可重命名)。