销毁并重新加载子组件 [英] Destroying and reloading a child component

查看:351
本文介绍了销毁并重新加载子组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要能够完全重新加载子组件.达到此目的的最好方法似乎是使用带有布尔值的简单*ngIf.将false设置为删除该组件,然后将其设置为true以重新初始化它,即:

I need to be able to completely reload a child component. It seems the best way to to acheive this is by using a simple *ngIf with a boolean value; Set false to remove the component, and then set to true to re-initialize it, ie:

<app-child *ngIf="enabled"></app-child>

但是,似乎仅执行此操作不足以快速删除/重新初始化该组件:

However, it seems that just doing this isn't enough to quickly remove/reinitialize the component:

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

相反,我必须先使用setTimeout,然后才能起作用:

Rather, I have to use a setTimeout before it will work:

reloadTree(){
  this.enabled = false;
  const self = this;
  setTimeout(function(){
    self.enabled = true;
  }, 1);
}

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

I presume this is to do with the way Angular renders templates? This isn't paricularly elegant- can anyone suggest a better way to acheive what I'm trying to do here? Thanks

推荐答案

因此,仅作记录用途,而无需尝试争论这样做是否是一种干净的方法,您可以通过以下方法解决标志切换的问题.主要思想是销毁子组件并随后再次创建它,您可以使用子组件上的简单 * ngIf 标志来完成此操作.

So just for the record and without trying to argue if it's a clean way to do it or not, here's how you can work around the problem with the flag toggling. The main idea is to destroy the child component and create it again afterwards, which you can do with a simple *ngIf flag on the child component.

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

If the flag is toggled to false, the child component is destroyed and completely removed from the DOM. Afterwards you can set it to true again to create a new instance (if I'm not mistaken here).

给定代码中的问题以及使用setTimeout方法的变通方法的需要是,角度需要注意对它们做出反应的更改.在这种情况下,两行代码的切换可能太快,以至于角度变化都无法控制(或者也许编译器甚至删除了第一行,所以什么也没有改变,虽然不确定),因此既不删除组件也不创建新实例.

The problem in the given code and the need for the workaround with the setTimeout method is that angular needs to be aware of changes to react to them. In this case the toggle in two lines of code may be just too quick for angular to even get hold of a change (or maybe the compiler even removes the first line at all, so nothing is ever changed, not sure though), therefore the component is neither removed nor is a new instance created.

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

我们需要做的是手动告诉Angle值已更改.这可以通过 ChangeDetectionRef 类完成,该类可以注入到组件中.在切换enabled标志之间,我们通知angular寻找更改,因此它可以通过完全删除组件来对此做出反应.然后我们可以将其设置为true来创建新实例.

What we need to do is to manually tell angular that a value has changed. This can be done through angulars ChangeDetectionRef class, which can be injected into the component. In between toggling the enabled flag, we notify angular to look for changes, so it can react to that by removing the component completely. Then we can set it back to true to create a new instance.

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

这篇关于销毁并重新加载子组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆