更新记录
1.1.0(2024-08-28) 下载此版本
将refType和refKey补充为组合唯一键,使同一个数据集可以通过不同的refKey在不同的树中定位。
1.0.0(2024-08-26) 下载此版本
初始发布,确定数据结构、功能接口及使用流程。
平台兼容性
阿里云 | 腾讯云 | 支付宝云 |
---|---|---|
√ | √ | √ |
云函数类插件通用教程
使用云函数类插件的前提是:使用HBuilderX 2.9+
nickw-tree
该功能的设计目的是将树形结构的处理与业务剥离,因此仅用于树形节点的管理,节点的其他信息由专门的表或数据集合处理。因此该模块的功能应为后端调用而不是前端。
该数据结构在写入性能随单颗树内数据量的增加而下降,但查询性能不受影响。
基本逻辑:对于树形数据,自最左侧叶子开始按左、右、父的方式排序,可以将树投影于数轴,因此为每个节点补充了其下最左侧子节点信息后,每个节点在数轴上的投影就由点转换为了线段。线段内的所有点都是该线段的子节点。
数据表及结构
- tree-node: 树形数据结构表
- tree-refer: 树形数据结构与扩展数据集合关系表。
- data-group: 扩展数据示例表
tree-node 树形数据结构
属性名 | 类型 | 说明 |
---|---|---|
_id | string |
节点唯一标识 |
rid | string |
隶属的根节点 |
pid | string |
父节点 |
level | int |
树高 |
snum | int |
节点在树内的顺序号 |
lfnum | int |
最左侧子节点的顺序号 |
tree-refer 树形数据结构与扩展数据集合关系表
属性名 | 类型 | 说明 |
---|---|---|
_id | string |
关系唯一标识 |
treeId | string |
树形数据结构表中根节点的_id |
refType | string |
扩展数据集合名称 |
refKey | string |
扩展数据集合中关联tree-node._id 的属性名称 |
data-group 扩展数据示例表,用于基本示例
属性名 | 类型 | 说明 |
---|---|---|
_id | string |
关系唯一标识 |
treeNodeId | string |
关联tree-node.id |
name | string |
数据组名称 |
code | string |
数据组的语义化标识 |
description | string |
备注信息 |
createTime | timestamp |
创建时间 |
API
方法名 | 说明 |
---|---|
createRoot | 创建树 |
removeRoot | 删除树 |
addNode | 增加节点 |
removeNode | 移除节点(及子节点) |
moveNode | 移动节点 |
getNodes | 节点查询 |
getParendNodes | 父节点查询 |
getSharedParendNode | 公共父节点查询 |
注: 由于任意节点的子节点数量 = snum - lfnum
,因此不提供是否存在子节点类的查询接口。
创建树
参数:
- refType: 扩展数据集合名称
- refKey: 扩展数据集合中关联
tree-node._id
的属性名称
返回值: tree-refer 表的数据,包括:
- treeId: 树形数据结构表中根节点的
_id
的值 - refType: 扩展数据集合名称
- refKey: 扩展数据集合中关联
tree-node._id
的属性名称
const treeNode = await createRoot({
refType: "data-group",
refKey: "treeNodeId",
});
删除树
参数: 根节点的 treeId
返回值: Boolean
const treeId = "string";
const success = await removeRoot(treeId);
增加节点
参数:
- treeNodeId: 节点唯一标识
- afterNode: Boolean,是否在指定节点的右侧添加节点,默认为 true
返回值: tree-node 表的数据,包括:
- id: 唯一键值
- rid: 隶属的根节点
- pid: 父节点
- level: 树高
- snum: 节点在树内的顺序号
- lfnum: 最左侧子节点的顺序号
/** 在指定节点的右侧添加节点 */
const treeNode = await addNode({
treeNodeId: "string",
afterNode: true,
});
/** 为指定节点添加子节点,且新增的节点是指定节点下最左侧的子节点 */
const treeNode = await addNode({
treeNodeId: "string",
afterNode: false,
});
移除节点(及子节点)
参数: 节点唯一标识 返回值: [{id: string}]
const treeNodeId = "string";
const success = await removeNode(treeNodeId);
移动节点
参数:
- treeNodeId: 节点唯一标识,需要移动的节点
- targetNodeId: 参考位置节点唯一标识
- afterNode: Boolean,是否在参考位置节点的右侧添加节点,默认为 true,否则作为参考位置节点的最左侧子节点。
返回值: Boolean
/** 移动到指定节点的右侧 */
const modifiedList = await moveNode({
treeNodeId: "string",
targetNodeId: "string",
afterNode: true,
});
/** 移动到指定节点的子级,且位于指定节点下最左侧 */
const modifiedList = await moveNode({
treeNodeId: "string",
targetNodeId: "string",
afterNode: false,
});
为什么没有返回移动后的节点信息?移动节点后,其他节点的
snum
和lfnum
也会发生变化,而前端使用时通常并不需要该信息(因为展示的树已经是正确结构),因此直接返回Boolean
。
公共父节点查询
查询两个节点的最近的公共父节点。
/** 查询指定节点的所有公共父节点 */
const nodeList = await getSharedParendNode({
treeNodeA: "object",
treeNodeB: "object",
});
节点查询
参数(如果 level=0,refType,treeNodeId 都不存在则查询结果为空数组):
- level: 树高,可选,限制返回的节点层级,为 0 时忽略其他参数返回所有根节点。
- refType: 扩展数据集合名称,可选(但是 refType + refKey 和 treeNodeId 不能同时为空(level=0 的特例除外))
- refKey: 扩展数据集合中关联
tree-node._id
的属性名称,可选 - treeNodeId: 节点唯一标识,可选(但是 refType 和 treeNodeId 不能同时为空(level=0 的特例除外))
- self: Boolean,是否包含查询节点自身(或根节点)
- levelLimit: 节点查询的子节点层级限制,可选,最小为 2,默认会返回所有子节点。
/** 特例参数查询,指定了level为0时忽略其他条件,用于查询所有根节点(通常没有任何意义) */
const nodeList = await getNodes({
level: 0,
});
/** 查询指定扩展类型的所有子节点,但不包括根节点 */
const nodeList = await getNodes({
refType: "group",
self: false,
});
/** 查询指定节点的3级以内子节点 */
const nodeList = await getNodes({
treeNodeId: "string",
levelLimit: 3,
});
父节点查询
参数:
- treeNodeId: 节点唯一标识,可选
- self: Boolean,是否包含查询节点自身
/** 查询指定节点的所有父节点 */
const nodeList = await getParentNodes({
treeNodeId: "string",
self: true,
});
节点查询的返回数据结构
泛型 T 是扩展数据集合中的数据类型。根节点对应的data
为 undefined。
interface TreeNode<T = any> {
id: "string";
rid: "string";
pid: "string";
level: "number";
snum: "number";
lfnum: "number";
data?: T;
}
测试
对象提供了test()
方法进行功能测试,并可以作为全流程的基本使用示例。