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

Angular中递归与迭代对比:如何实现迭代式分类树?

迭代方式实现Angular无限层级分类树

首先修正你的分类接口拼写错误(原subcateogories应为subcategories):

export interface Category {
  category: string;
  subcategories: Category[];
}

迭代实现的核心思路是通过栈遍历嵌套数据,将其转换为带深度标识的扁平数组,再用单层循环渲染,完全避免组件递归。以下是完整实现:

1. 迭代分类树组件代码

组件类(iterative-tree.component.ts)

import { Component, Input } from '@angular/core';
import { Category } from '../path-to-your-category-interface';

@Component({
  selector: 'app-iterative-tree',
  templateUrl: './iterative-tree.component.html',
  styleUrls: ['./iterative-tree.component.scss']
})
export class IterativeTreeComponent {
  private _rawCategories: Category[] = [];
  flattenedCategories: (Category & { depth: number })[] = [];

  @Input() set categories(categories: Category[] | undefined) {
    if (categories) {
      this._rawCategories = categories;
      this.flattenedCategories = this.flattenWithIteration(categories);
    }
  }

  // 栈迭代方式扁平化嵌套分类,添加深度标识
  private flattenWithIteration(categories: Category[], initialDepth = 0): (Category & { depth: number })[] {
    const result: (Category & { depth: number })[] = [];
    // 初始化栈,每个元素包含分类数据和当前深度
    const stack = categories.map(cat => ({ ...cat, depth: initialDepth }));

    while (stack.length > 0) {
      const currentItem = stack.pop()!;
      result.push(currentItem);

      // 子分类倒序入栈,保证渲染顺序和递归版本一致
      if (currentItem.subcategories?.length) {
        const subCatsWithDepth = currentItem.subcategories
          .map(subCat => ({ ...subCat, depth: currentItem.depth + 1 }))
          .reverse();
        stack.push(...subCatsWithDepth);
      }
    }

    // 反转结果恢复原顺序
    return result.reverse();
  }

  addNewEntry(category: Category) {
    // 实现添加子分类逻辑,和递归版本一致
    if (!category.subcategories) {
      category.subcategories = [];
    }
    category.subcategories.push({ category: '新分类', subcategories: [] });
    // 更新扁平化数组
    this.flattenedCategories = this.flattenWithIteration(this._rawCategories);
  }
}

组件模板(iterative-tree.component.html)

<ul class="list-disc">
  <ng-container *ngFor="let item of flattenedCategories">
    <!-- 根据深度设置缩进,和递归版本的ml-4层级对应 -->
    <li [class]="'ml-' + (item.depth * 4) + ' mt-1'">
      {{ item.category }}
      <button (click)="addNewEntry(item)" type="button" class="ml-4 text-blue-700 border border-blue-700 hover:bg-blue-700 hover:text-white focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-full text-sm text-center inline-flex items-center dark:border-blue-500 dark:text-blue-500 dark:hover:text-white dark:focus:ring-blue-800 dark:hover:bg-blue-500">
        <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
          <path d="M10.75 6.75a.75.75 0 00-1.5 0v2.5h-2.5a.75.75 0 000 1.5h2.5v2.5a.75.75 0 001.5 0v-2.5h2.5a.75.75 0 000-1.5h-2.5v-2.5z"></path>
        </svg>
      </button>
    </li>
  </ng-container>
</ul>

2. 调用迭代组件

和递归版本的调用方式完全一致:

<div class="px-16">
  <div>
    <app-iterative-tree [categories]="fetchedData"></app-iterative-tree>
  </div>
</div>

实现说明

  • 完全采用迭代逻辑:通过栈数据结构遍历所有层级的分类,没有使用任何组件递归或函数递归
  • 保持UI一致性:通过depth属性动态设置缩进,和递归版本的视觉效果完全一致
  • 支持动态更新:添加新分类后重新生成扁平化数组,保证视图同步

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 08:24:57