You need to enable JavaScript to run this app. Angular 7应用下Mat Tree嵌套节点的全路径定向展开实现方案
优惠活动
大模型
产品
解决方案
定价
更多

Angular 7应用下Mat Tree嵌套节点的全路径定向展开实现方案

深层嵌套Mat Tree节点全路径展开实现方案

核心实现逻辑

针对Angular 7版本的Mat Tree(嵌套数据源模式),实现深层节点全路径展开只需要两个核心环节,完全适配大数量级下的性能要求,不需要递归遍历全量树数据:

  • 依托数据里csrSectionNum的点分路径编码特性,直接拆解生成目标节点的全路径分级标识列表
  • 顺着路径从根节点开始逐级匹配对应节点,将所有路径节点通过TreeControl设置为展开状态
    可以完全解决现有逻辑仅能展开一级节点的问题,比如目标为9.2.1.2时,会依次展开9、9.2、9.2.1、9.2.1.2全路径上的所有节点。

分步实现代码

1. 拆解生成目标节点的全路径标识列表

利用csrSectionNum的点分格式,不需要从根开始递归找父节点,直接按规则拼接生成每一级的节点标识:

/**
 * 根据目标csrSectionNum生成全路径的节点标识列表
 * @param targetCsrNum 示例:传入'9.2.1.2'
 * @returns 逐级路径数组 ['9', '9.2', '9.2.1', '9.2.1.2']
 */
private getFullPathCsrList(targetCsrNum: string): string[] {
  const segments = targetCsrNum.split('.');
  const pathList: string[] = [];
  segments.reduce((prevPath, currentSeg, index) => {
    const currentLevelPath = index === 0 ? currentSeg : `${prevPath}.${currentSeg}`;
    pathList.push(currentLevelPath);
    return currentLevelPath;
  }, '');
  return pathList;
}

这一步的时间复杂度和树总数据量无关,只和节点的嵌套深度有关,哪怕几万条树数据也不会产生性能开销。

2. 逐级收集路径上的匹配节点

拿到全路径标识列表后,从根节点开始收缩搜索范围,不需要扫描全树的所有分支:

/**
 * 从嵌套树数据中按路径收集所有匹配的节点实例
 * @param rootTreeData 你的原始嵌套节点数组
 * @param fullPathList getFullPathCsrList返回的路径列表
 */
private getPathMatchedNodes(rootTreeData: any[], fullPathList: string[]): any[] {
  const matchedNodes: any[] = [];
  // 初始搜索范围为所有根节点
  let searchRange = rootTreeData;
  for (const csrNum of fullPathList) {
    // 在当前搜索范围内找匹配csrSectionNum的节点
    const currentNode = searchRange.find(node => node.csrSectionNum === csrNum);
    if (!currentNode) break; // 路径断裂时直接终止搜索
    matchedNodes.push(currentNode);
    // 下一轮搜索范围收缩为当前节点的子节点列表,不遍历其他同级分支
    searchRange = currentNode.children || [];
  }
  return matchedNodes;
}

这个遍历逻辑的扫描范围仅覆盖目标路径上的分支,不会触达无关的同级节点,大数据量下依然能保持快速响应。

3. 调用TreeControl设置节点展开

拿到路径上的所有节点实例后,直接调用Mat Tree内置的展开方法即可,不需要手动修改数据源的展开标记:

// 假设你已经按嵌套树的初始化方式配置了TreeControl:
// treeControl = new NestedTreeControl<any>(node => node.children);

/**
 * 修改操作完成后调用,自动展开到目标节点
 * @param targetCsrNum 修改完成的目标分区编号
 * @param latestTreeData 最新的树数据源(保存接口返回后的最新数据)
 */
autoExpandToTargetSection(targetCsrNum: string, latestTreeData: any[]) {
  // 生成全路径标识列表
  const fullPath = this.getFullPathCsrList(targetCsrNum);
  // 收集路径上的所有匹配节点
  const pathNodes = this.getPathMatchedNodes(latestTreeData, fullPath);
  // 逐个设置节点为展开状态
  pathNodes.forEach(node => {
    this.treeControl.expand(node);
  });
}

常见适配注意点

  • 当前使用的是嵌套结构的TreeControl,expand()方法只要传入对应的节点引用就可以生效,不需要额外维护节点ID和实例的映射表
  • 避免为了匹配节点写全树递归逻辑,这种方式在大数量级下会出现明显的卡顿,利用csrSectionNum的路径特性可以把扫描范围降到最低
  • 触发展开逻辑时一定要传入最新的树数据源,不要使用旧的缓存数据,否则会因为节点引用更新导致展开失效
  • 之前的一级节点展开问题,本质是原逻辑只匹配了根节点层级的csrSectionNum,没有顺着路径逐级匹配后续深层节点

内容的提问来源于stack exchange,提问作者Santhosh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.26 20:36:00