OP 似乎认为它不适合他的需要,或者不优雅,但似乎 Vale Steve 的回答是这里最合乎逻辑的方法。
在我的情况下,我需要等待 2 个子组件初始化,它们控制着我的应用程序中的左右面板。我有两个子组件都将它们的初始化声明为共享服务:
constructor(
public _navigate: RouteNavigationService // service shared between all child components and parent
){}
ngOnInit() {
this._navigate.setChildInit(this.panel);
}
共享服务(RouteNavigationService):
private _leftChildInit = new Subject();
private _rightChildInit = new Subject();
leftChildInit$ = this._leftChildInit.asObservable();
rightChildInit$ = this._rightChildInit.asObservable();
setChildInit(panel){
switch(panel){
case 'leftPanel':
console.log('left panel initialized!');
this._leftChildInit.next(true);
break;
case 'rightPanel':
console.log('right panel initialized!');
this._rightChildInit.next(true);
break;
}
}
然后在我的父组件中,我使用zip 方法将多个 Observable 组合在一起(您也可以在此处添加其他子组件)并等待它们全部完成:
childInitSub: Subscription;
constructor(
public _navigate: RouteNavigationService
) {
this.childInitSub = Observable.zip( // WAIT FOR BOTH LEFT & RIGHT PANELS' ngOnInit() TO FIRE
this._navigate.leftChildInit$,
this._navigate.rightChildInit$).subscribe(data =>
// Both child components have initialized... let's go!
);
}
OP 在评论中声明
“我不喜欢这样,因为每次我添加一个新组件我都需要
等待一个额外的 onInit 事件并且必须实现它”
但实际上,您所要做的就是在您的服务中为新的子组件 ngOnInit 创建另一个 Subject,并在父组件的 zip 方法中添加一个额外的行。
请注意,这里接受的答案,使用ngAfterViewInit() 与上面的相当不同。在我的例子中,使用ngAfterViewInit() 会产生一个ExpressionChangedAfterItHasBeenCheckedError,这超出了这个问题的范围,但可以证明这种方法实际上并没有做同样的事情。
相比之下,上述方法实际上只是作为所有子组件的ngOnInit() 事件已触发的直接结果触发。