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
相关产品推荐
相关产品推荐

