在工作时,遇到了后端的返回的response是一个如下结构的数据的对象(对象中的属性值是对象属性),需要把下面对象中的currentYears、previousYears两个的数据都在html中分别进行显示。
year =
{
currentYears:[{month:'',day:''},{month:'',day:''}],
previousYears:{2016:[{month:'',day:''},{month:'',day:''}],2017:[{month:'',day:''},{month:'',day:''}]}
}
当时采用的方法是:*ngFor 循环
一般来说,*ngFor使用来循环数组的,循环对象会有报错:Cannot find a differ supporting object 'object' of type 'object'. NgFor only supports binding to Iterables such as Arrays.
这个时候最直接的就是使用keyValue这个管道https://angular.io/api/common/KeyValuePipe(本文后面会写到将对象转化成数组从而再循环处理)
<ng-container *ngIf="currentYears.length>0; then currentYears; else previousYears"></ng-container>
//html
<div #currentYears>
<div *ngFor="let current of currentYears">
{{current.month}}-{{current.year}}
</div>
</div>
<div #previousYears>
<div *ngFor="let preivous of previousYears | keyValue">
<span>{{preivous.key}}</span>//2016, 2017
<div *ngFor="let item of preivous.value | keyValue:unsorted">
<span>{{item.month}}-{{item.day}}</span>
</div>
</div>
</div>
<script>
//这里展示的是不排序的显示,当然如果有排序的要求,可以根据实际情况进行编写排序的程序代码
unsorted(a: any, b: any):Number {
return 0;
}
//比如降序的
desendingOrder(a: KeyValue < string, any >, b: KeyValue < string, any >) {
const s = a.key;
const t = b.key;
return t > s ? 1 : (s > t ? -1 : 0);
}
</script>
//当previousYear这个对象有数据,输出效果如下:
2016:month-day
2017: month-day
在上述代码中,我们使用了 *ngFor
指令来循环遍历 previousYears
对象。*ngFor="let year of previousYears | keyvalue"
表示我们要遍历 previousYears
对象,并将键(年份)和值(日期数组)存储在 year
变量中。然后使用 *ngFor="let item of year.value"
,在每个年份内部循环遍历日期数组。在模板中使用插值绑定 {{ }}
来显示具体的月份和日期。
其实在发现上面的这个处理方法的时候,最初使用的处理方法是使用自定义指令:
```html
<div appYearRenderer [years]="previousYears"></div>
```
```typescript
import { Directive, Input, ElementRef } from '@angular/core';
@Directive({
selector: '[appYearRenderer]'
})
export class YearRendererDirective {
@Input('appYearRenderer') years: any;
constructor(private el: ElementRef) { }
ngOnInit() {
for (let year in this.years) {
const yearDiv = document.createElement('div');
yearDiv.innerHTML = `<h2>${year}</h2>`;
const ul = document.createElement('ul');
this.years[year].forEach(obj => {
const li = document.createElement('li');
li.innerText = `${obj.month} - ${obj.day}`;
ul.appendChild(li);
});
yearDiv.appendChild(ul);
this.el.nativeElement.appendChild(yearDiv);
}
}
}
```
在上面的示例中,我们创建了一个名为 `appYearRenderer` 的指令,它接受一个名为 `years` 的输入属性,在组件中传入 `previousYears` 对象。在指令的 `ngOnInit` 生命周期钩子中,我们使用原生 JavaScript 创建 HTML 元素并将其附加到指令所在的元素中,实现了数据的渲染和展示。
后面经过在冲浪时又想起了这个问题,发现了另外的处理方法,就是使用Obejct.key()将对象进行转化:
<ng-container *ngIf="currentYears.length>0; then currentYears; else previousYears"></ng-container>
<div #currentYears>
<div *ngFor="let current of currentYears">
{{current.month}}-{{current.year}}
</div>
</div>
<div #previousYears>
<div *ngFor="let preivous of Object.key(previousYears)">
<span>{{preivous}}</span>//2016, 2017
<div *ngFor="let item of previousYears[preivous]">
<span>{{item.month}}-{{item.day}}</span>
</div>
</div>
</div>
总而言之,以上三种方法能达到一样的效果,具体使用哪种方法,就看各位的喜好了!