我需要能够完全重新加载子组件。似乎最好的方法是使用带有布尔值的简单*ngIf
;设置为false以删除组件,然后设置为true以重新初始化它,即:
<app-child *ngIf="enabled"></app-child>
然而,似乎这样做并不足以快速删除/重新初始化组件:
reloadTree(){
this.enabled = false;
this.enabled = true; // doesn't work- child ngOnInit isn't called
}
相反,我必须先使用setTimeout
才能运作:
reloadTree(){
this.enabled = false;
const self = this;
setTimeout(function(){
self.enabled = true;
}, 1);
}
我认为这与Angular呈现模板的方式有关?这不是特别优雅 - 任何人都可以建议一个更好的方法来实现我在这里尝试做的事情吗?感谢
答案 0 :(得分:2)
所以只是为了记录而不试图争论它是否是一个干净的方式来做到这一点,以下是如何通过旗帜切换来解决问题。主要思想是销毁子组件并在之后再次创建它,您可以使用子组件上的简单 * ngIf 标志来执行此操作。
如果将标志切换为 false ,则子组件将被销毁并从DOM中完全删除。然后你可以再次将它设置为 true 来创建一个新实例(如果我在这里没有弄错的话)。
给定代码中的问题以及使用setTimeout
方法的变通方法的需要是角度需要知道对它们作出反应的变化。在这种情况下,两行代码中的切换对于角度来说可能太快,甚至无法保持变化(或者编译器甚至可以删除第一行,因此没有任何改变,但不确定),因此组件既未被删除也未创建新实例。
reloadTree(){
this.enabled = false; // switching to false
this.enabled = true; // and back to true
// this does not notify angular that something has actually changed
}
我们需要做的是手动告知角度值已更改。这可以通过角度ChangeDetectionRef类来完成,可以将其注入组件中。在切换enabled
标志之间,我们通知angular查找更改,因此它可以通过完全删除组件来对此做出反应。然后我们可以将其设置为true以创建新实例。
constructor(private changeDetector: ChangeDetectorRef){}
reloadTree(){
this.enabled = false;
// now notify angular to check for updates
this.changeDetector.detectChanges();
// change detection should remove the component now
// then we can enable it again to create a new instance
this.enabled = true;
}