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



我将异步数据从父组件传递到子组件。并且子部分需要了解数据的长度才能做某事。

问题是如何使用" 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>
  1. 将您的输入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);
    })
}
  1. 在孩子的ngOnChanges期间这样做。例如,请参阅此处。https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#! #onchanges

更简单的解决方案:

ngOnChanges(changes: SimpleChanges) {
    if (changes['items'].currentValue) {
        this.items = items
    }
}

您可以使用一个设置器:

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
     }    
}

最新更新