使用递归方法呈现嵌套对象

时间:2018-02-04 17:50:44

标签: arrays angular recursion

我有一个有点复杂的对象,包括嵌套对象,如下所示

      "data": {
        "John": {
          "title": "John",
          "value": "john"
        },
        "Ben": {
          "title": "Ben",
          "value": "ben"
        },
        "Workers": {
          "title": "Working Data",
          "startData": {
            "title": "Start Date",
            "value": "Mon, 27 Nov 2017 16:57:56 GMT"
          },
          "isPermanant": {
            "title": "Is Permanant",
            "value": "True"
          }
        },
        "Family": {
          "title": "Family Data",
          "familyMembers": {
            "title": "Family Members",
            "value": "4"
          },
          "pets": {
            "title": "Pets",
            "value": "2"
          }
        },
        "education": {
          "title": "Education Details",
          "degree": {
            "title": "Degree",
            "value": "Yes"
          },
          "graduated": {
            "title": "Graduated Year",
            "value": "2015"
          }
        }

预期结果是这样的

    <p>John <span>john</span><p>
    <p>Ben <span>ben</span><p>

<p>Working Data<p>
    <p>Start Date <span>Mon, 27 Nov 2017 16:57:56 GMT</span><p>
    <p>Is Permanant <span>True</span><p>

<p>Family Data<p>
    <p>Family Members <span>4</span><p>
    <p>Pets <span>2</span><p>

<p>Education Details<p>
    <p>Degree <span>Yes</span><p>
    <p>Graduated Year<span>2015</span><p>

我创建了一个使用递归方式显示数据的组件

import { Component, Input, OnInit } from '@angular/core'

@Component({
    selector: 'timeline-data',
    template: 'timeline-data.html' 
})

export class TimelineDataComponent implements OnInit {
    @Input('data') data: any[];

    ngOnInit() {}
}

timeline-data.html如下

<ng-container *ngIf="data.length">
     <ng-container *ngFor="let item of data">
          <ng-container *ngIf="item.value">
               <p>{{ item.title }} <span>{{ item.value }}</span></p>
          </ng-container>
          <ng-container *ngIf="!item.value">
               <timeline-data [data]="[item]"></timeline-data>
          </ng-container>
      <ng-container>
<ng-container>

但是当我跑这个角时,给我一个RangeError: Maximum call stack size exceeded

我在这里做错了什么?我应该如何展示这个?提前谢谢。

1 个答案:

答案 0 :(得分:1)

根据您的示例html,很难进行递归渲染,最终不会使用嵌套的li标记。

我采用了稍微不同的方法,并使用了一个带有额外条件的无序列表来消除第一次迭代中的空import { Component, Input } from '@angular/core'; @Component({ selector: 'tree-component, [tree-component]', template: ` // omit the <li> wrapper for the "parent" iteration <ng-container *ngIf="parent"> <tree-item [data]="data"></tree-item> </ng-container> <li *ngIf="!parent"> <tree-item [data]="data"></tree-item> </li> ` }) export class TreeComponent { @Input() data: object; @Input() parent = false; } 。如果有人有更好的方法来做到这一点,我会全力以赴:)

我将渲染分为两个主要部分:

<强> tree.component.ts

import { Component, Input } from '@angular/core';

@Component({
  selector: 'tree-item',
  template: `
    // iterate over the keys for each data item

    <ng-container *ngFor="let key of data | keys; let i = index;">

      // if the value is not an object, output the values
      // I assumed there would only be two values to wrap the second
      // value in a <span> according to your sample

      <ng-container *ngIf="!isObject(data[key])">
        <ng-container *ngIf="i === 0">{{ data[key] }}</ng-container>
        <span *ngIf="i === 1">{{ data[key] }}</span>
      </ng-container>

      // if the value is an object, recursively render the tree-component

      <ul tree-component *ngIf="isObject(data[key])" [data]="data[key]"></ul>
    </ng-container>
  `
})
export class TreeItemComponent {

  @Input()
  data: object;

  isObject(value: any): boolean {
    return value instanceof Object && value.constructor === Object;
  }

}

<强>树item.component.ts

import { PipeTransform, Pipe } from '@angular/core';

@Pipe({
  name: 'keys'
})
export class KeysPipe implements PipeTransform {
  transform(value, args: string[]): any {
    return Object.keys(value);
  }
}

和一个管道实用程序,用于获取每个对象的键, keys.pipe.ts

<tree-component [data]="data" [parent]="true"></tree-component>

提供您的数据和实施:

var pageWidth = $(window).width();
var body= document.getElementsByTagName(‘body’)[0];
var script= document.createElement(‘script’);
script.type= ‘text/javascript’;
if (pageWidth > 1024) {
...

你最终得到了这个Plunkr的结果:GitHub