销毁并重新加载子组件

Ini*_*igo 4 angular

我需要能够完全重新加载子组件。实现这一点的最佳方法似乎是使用*ngIf带有布尔值的 simple ;设置false删除组件,然后设置true重新初始化,即:

<app-child *ngIf="enabled"></app-child>
Run Code Online (Sandbox Code Playgroud)

但是,似乎仅仅这样做还不足以快速删除/重新初始化组件:

reloadTree(){
  this.enabled = false;
  this.enabled = true; // doesn't work- child ngOnInit isn't called
}
Run Code Online (Sandbox Code Playgroud)

相反,我必须使用 asetTimeout才能工作:

reloadTree(){
  this.enabled = false;
  const self = this;
  setTimeout(function(){
    self.enabled = true;
  }, 1);
}
Run Code Online (Sandbox Code Playgroud)

我认为这与 Angular 渲染模板的方式有关?这不是特别优雅 - 任何人都可以提出更好的方法来实现我在这里要做的事情吗?谢谢

Ben*_*idt 23

所以只是为了记录,而不是试图争论这是否是一种干净的方法,这里是你如何解决标志切换问题的方法。主要思想是销毁子组件并在之后再次创建它,您可以在子组件上使用简单的*ngIf标志来完成。

如果该标志切换为false,则子组件将被销毁并从 DOM 中完全删除。之后,您可以再次将其设置为true以创建一个新实例(如果我没记错的话)。

给定代码中的问题以及对该方法的解决setTimeout方法的需求是 angular 需要了解更改以对其做出反应。在这种情况下,两行代码中的切换可能太快了,angular 甚至无法掌握更改(或者编译器甚至可能根本删除了第一行,因此没有任何更改,但不确定),因此组件既不会被移除,也不会被创建新的实例。

reloadTree(){
  this.enabled = false; // switching to false
  this.enabled = true; // and back to true 
  // this does not notify angular that something has actually changed
}
Run Code Online (Sandbox Code Playgroud)

我们需要做的是手动告诉 angular 某个值已更改。这可以通过angulars进行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; 
}
Run Code Online (Sandbox Code Playgroud)