我有一个有点复杂的对象,包括嵌套对象,如下所示
"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
我在这里做错了什么?我应该如何展示这个?提前谢谢。
答案 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