You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular不使用mat-tree如何实现无限嵌套自定义树模型

树结构示例

实现无限层级嵌套树方案

不依赖mat-tree实现任意深度树渲染的核心方案是递归组件:树形结构的每个节点渲染逻辑完全一致,将单节点逻辑抽为独立组件后,组件可以在自身模板内调用自身,自动适配无限层级,不需要硬编码固定层数。

具体实现步骤
  • 定义通用树节点数据结构
    所有层级的节点统一使用相同结构,保证递归时数据格式一致:
    interface TreeNode {
      name: string;
      children?: TreeNode[];
      // 可自行扩展id、联系人信息等业务字段
    }
    
  • 编写可递归的单节点组件
    以Angular为例,新建独立的树节点组件,接收单个节点数据作为输入,自身处理展开收起、hover交互,碰到有子节点的场景直接嵌套调用自身:
    组件逻辑代码(tree-node.component.ts):
    import { Component, Input } from '@angular/core';
    
    @Component({
      selector: 'app-tree-node',
      templateUrl: './tree-node.component.html',
      styles: [`
        .tree-children {
          padding-left: 20px; /* 左缩进区分层级,可自行调整数值 */
        }
        .expand-icon {
          display: inline-block;
          width: 16px;
          font-size: 12px;
        }
      `]
    })
    export class TreeNodeComponent {
      @Input() node: TreeNode;
      isExpanded = false;
      showActionBtns = false;
    
      toggleExpand() {
        if (this.node.children?.length) {
          this.isExpanded = !this.isExpanded;
        }
      }
    
      handleMouseEnter() {
        this.showActionBtns = true;
      }
    
      handleMouseLeave() {
        this.showActionBtns = false;
      }
    }
    
    组件模板代码(tree-node.component.html):
    <div class="tree-node">
      <!-- 当前节点内容区,复用原有父节点的交互逻辑 -->
      <div 
        class="tree-node-content"
        (mouseenter)="handleMouseEnter()"
        (mouseleave)="handleMouseLeave()"
      >
        <p class="phonebook-title" (click)="toggleExpand()">
          <!-- 展开收起标识,可替换为自定义图标 -->
          <span class="expand-icon" *ngIf="node.children?.length">
            {{ isExpanded ? '▼' : '▶' }}
          </span>
          {{ node.name }}
          <!-- 原有新增、编辑、删除等操作按钮放在此处,通过*ngIf="showActionBtns"控制显示 -->
        </p>
      </div>
      <!-- 子节点渲染区:展开且存在子节点时渲染 -->
      <div class="tree-children" *ngIf="isExpanded && node.children?.length">
        <!-- 遍历子节点,递归调用当前组件,自动适配任意深度嵌套 -->
        <app-tree-node
          *ngFor="let child of node.children"
          [node]="child"
        ></app-tree-node>
      </div>
    </div>
    
  • 在业务页面使用树组件
    原有页面不需要再写多层嵌套循环,直接遍历根节点数组传入递归组件即可:
    <div class="phonebook-tree">
      <app-tree-node
        *ngFor="let rootNode of phonebookTreeModelArray"
        [node]="rootNode"
      ></app-tree-node>
    </div>
    
补充说明
  • 递归渲染不会触发死循环,只要树形数据不存在循环引用(即某节点的children数组中包含自身或上层祖先节点)即可,常规业务接口返回的树形结构均满足该要求。
  • 如果需要保留“同层级同时仅展开一个节点”的逻辑,只需要给递归组件加输出事件,节点触发展开时通知父级关闭同层级其他节点的展开状态即可。
  • 若需要默认展开指定节点,可在节点数据中增加defaultExpanded标识,在组件初始化时读取该标识给isExpanded赋初始值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 18:36:22