Angular9动态迭代嵌套JSON数组,解决深层数组DOM渲染位置问题
解决Angular9中嵌套数组的动态迭代渲染问题
我来帮你搞定这个深层数组渲染的问题!你的核心痛点在于没有对嵌套数组做递归处理,同时类型判断的逻辑也有点小问题,导致深层的elementFour数组没法正确展示。下面一步步给你解决:
问题根源分析
- 类型判断不准确:你用
typeof(val) !== 'object'来判断是否为数组,但JS里数组的typeof结果也是object,而且null的typeof也是object,这会导致判断逻辑出错。 - 缺乏递归处理:当前的表格渲染只处理了一层数组,当数组里的元素又是数组时(比如
elementFour的值),没有继续递归渲染其内部结构,直接把数组当成普通值显示了。
分步解决方案
1. 修复类型判断方法
把isNotArray改成用Array.isArray()来准确判断数组,同时排除null的干扰:
isNotArray(val: any): boolean { return !Array.isArray(val) && val !== null; }
2. 给表格添加递归渲染逻辑
在<td>里再次判断当前值是否为数组,如果是就递归渲染对应的结构(可以复用你的app-tree-view组件,也可以重复表格逻辑)。修改HTML中的<td>部分:
<td *ngFor="let value of allValues(res.value)"> <ng-container *ngIf="isNotArray(value); else nestedArray"> {{value | dataType}} </ng-container> <ng-template #nestedArray> <app-tree-view [(treeData)]="value"></app-tree-view> <table border="1"> <thead> <th *ngFor="let nestedKey of allKeys(value);"> {{nestedKey | sentenceCase}} </th> </thead> <tbody> <tr> <td *ngFor="let nestedVal of allValues(value)"> {{nestedVal | dataType}} </td> </tr> </tbody> </table> </ng-template> </td>
3. 优化allKeys和allValues方法
让这两个方法能处理嵌套数组的情况,递归提取键和值:
allKeys(value: any[]): string[] { return value.map(item => { // 如果当前元素是数组,递归提取内部的键 if (Array.isArray(item)) { return this.allKeys(item).join(', '); } return Object.keys(item)[0]; }); } allValues(value: any[]): any[] { return value.map(item => { if (Array.isArray(item)) { return this.allValues(item); } return Object.values(item)[0]; }); }
4. 可选:封装递归组件(更优雅)
如果嵌套层级可能更深,建议把数组渲染的逻辑封装成一个独立组件(比如app-nested-renderer),这样在需要递归的地方直接调用组件即可,避免HTML代码重复。
完整修改后的代码示例
app.component.ts
import { Component } from '@angular/core'; const JSON_RESPONSE = { nodeOne: 'string', nodeTwo: new Date(), nodeThree: 123, nodeFour: [ { elementOne: 'string' }, { elementTwo: 456 }, { elementThree: 789 }, { elementFour: [ { elementFive: new Date() }, { elementSix: 101112 } ] } ] }; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { response = JSON_RESPONSE; isNotArray(val: any): boolean { return !Array.isArray(val) && val !== null; } allKeys(value: any[]): string[] { return value.map(item => { if (Array.isArray(item)) { return this.allKeys(item).join(', '); } return Object.keys(item)[0]; }); } allValues(value: any[]): any[] { return value.map(item => { if (Array.isArray(item)) { return this.allValues(item); } return Object.values(item)[0]; }); } returnZero() { return 0; } }
app.component.html
<div *ngFor="let res of response | keyvalue : returnZero"> {{res.key | sentenceCase}} : <span *ngIf="isNotArray(res.value); else arrayValues">{{res.value | dataType}}</span> <ng-template #arrayValues> <app-tree-view [(treeData)]="res.value"></app-tree-view> <table border="1"> <thead> <th *ngFor="let key of allKeys(res.value);"> {{key | sentenceCase}} </th> </thead> <tbody> <tr> <td *ngFor="let value of allValues(res.value)"> <ng-container *ngIf="isNotArray(value); else nestedArray"> {{value | dataType}} </ng-container> <ng-template #nestedArray> <app-tree-view [(treeData)]="value"></app-tree-view> <table border="1"> <thead> <th *ngFor="let nestedKey of allKeys(value);"> {{nestedKey | sentenceCase}} </th> </thead> <tbody> <tr> <td *ngFor="let nestedVal of allValues(value)"> {{nestedVal | dataType}} </td> </tr> </tbody> </table> </ng-template> </td> </tr> </tbody> </table> </ng-template> </div>
这样修改后,深层的elementFour数组就能正确递归渲染,和你想要的示例图效果一致啦!
内容的提问来源于stack exchange,提问作者Nimish
相关产品推荐
相关产品推荐

