Angular 2如何让子组件等待异步数据准备好
Posted
技术标签:
【中文标题】Angular 2如何让子组件等待异步数据准备好【英文标题】:Angular 2 how to make child component wait for async data to be ready 【发布时间】:2017-05-14 08:02:20 【问题描述】:我正在将异步数据从父组件传递到子组件。并且子组件需要知道数据的长度才能做某事。
问题是子组件无法使用“Oninit”挂钩来完成工作,因为此时数据不可用。那我该怎么做呢?
父组件代码如下:
@Component(
moduleId: module.id,
selector: 'parent',
template: `<div>
<child [items]="items | async">
</div>`
)
export class Parent implements OnInit
items: Items[];
constructor(
private itemService: ItemService,
private router: Router
)
ngOnInit()
this.itemService.getItemss()
.subscribe(
items => this.items = items,
error => this.errorMessage = <any>error
);
子组件看起来像:
@Component(
moduleId: module.id,
selector: 'child',
template: `<div>
<div *ngFor="let itemChunk of itemChunks"></div>
content here
</div>`
)
export class child implements OnInit
@Input() items: Items[];
itemChunks: Items[][];
ngOnInit()
this.itemChunks = this.chunk(this.Items);
chunk(items: Items[])
let result = [];
for (var i = 0, len = items.length; i < len; i += 6) // this line causes the problem since 'items' is undefined
result.push(items.slice(i, i + 6));
return result;
处理此问题的最佳做法是什么?
【问题讨论】:
【参考方案1】:有三种方法可以做到这一点:
-
将
*ngIf
放在父级中。仅当父母的items
准备好时才渲染孩子。
<div *ngIf="items">
<child [items]="items | async">
</div>
-
将您的输入
getter
setter
分开。然后在设置值时执行操作,您也可以使用 RxJS BehaviorSubject
。
private _items = new BehaviorSubject<Items[]>([]);
@Input() set items(value: Items[])
this._items.next(value);
get items()
return this._items.getValue();
ngOnInit()
this._items.subscribe(x =>
this.chunk(x);
)
-
在孩子的
ngOnChanges
期间进行。例如,请参阅此处。 https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#onchanges
【讨论】:
最终选择选项 2。行为完全符合预期。非常感谢。 @Milad,对不起?我不明白你。 @Milad,如果您足够仔细地检查已回答的日期时间,您会发现 Chybie 的回答比您早。因此,我将他的回答标记为已接受。 value setter 就足够了,但我喜欢 Observable 的味道 :) 感谢您的回答!看到它后它是“明显的”,但它在今天的一部分时间里一直躲在我面前。【参考方案2】:你可以使用setter:
export class child implements OnInit
itemChunks: Items[][];
private _items ;
//bellow will get called when ever the items are passed in by the parent component
@Input( 'items' ) set items ( items: Items[] )
this._items = items;
this.itemChunks = this.chunk(this._items);
chunk(items: Items[])
let result = [];
for (var i = 0, len = items.length; i < len; i += 6) // this line causes the problem since 'items' is undefined
result.push(items.slice(i, i + 6));
return result;
顺便说一句,我觉得你的父组件也不对,应该是:
@Component(
moduleId: module.id,
selector: 'parent',
template: `<div>
<child [items]="items | async">
</div>`
)
export class Parent implements OnInit
items: Items[];
constructor(
private itemService: ItemService,
private router: Router
)
this.items = this.itemService.getItemss(); // if getItemss is returning an observable, which I think it does
【讨论】:
感谢您的回答。但是 itemService 目前不返回可观察的。将来可能会。【参考方案3】:更简单的解决方案:
ngOnChanges(changes: SimpleChanges)
if (changes['items'].currentValue)
this.items = items
【讨论】:
值得一提的是,ngOnChanges会在ngOnInit之前运行。以上是关于Angular 2如何让子组件等待异步数据准备好的主要内容,如果未能解决你的问题,请参考以下文章