Angular 2如何使子组件等待asyn数据准备就绪

All*_*ang 25 angular

我将异步数据从父组件传递到子组件.并且子组件需要知道数据的长度才能执行某些操作.

问题是子组件不能使用'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
            );
    }

}
Run Code Online (Sandbox Code Playgroud)

子组件看起来像:

@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;
    }
}
Run Code Online (Sandbox Code Playgroud)

处理这个问题的最佳做法是什么?

Chy*_*bie 51

有三种方法可以做到这一点:

  1. 放入*ngIf父母.只有当父母items已准备好时才渲染子项.

    <div *ngIf="items">
       <child [items]="items | async">
    </div>
    
    Run Code Online (Sandbox Code Playgroud)
  2. 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);
        })
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在做它ngOnChanges的孩子.例如,请参阅此处.https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#onchanges


Dan*_*Waw 10

更简单的解决方案:

ngOnChanges(changes: SimpleChanges) {
    if (changes['items'].currentValue) {
        this.items = items
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 值得一提的是,**ngOnChanges** 将在 **ngOnInit** 之前运行。 (4认同)