Angular完全销毁动态创建的组件

Posted

技术标签:

【中文标题】Angular完全销毁动态创建的组件【英文标题】:Angular Destroying a dynamically created component completely 【发布时间】:2019-02-18 10:15:12 【问题描述】:

我使用以下方法创建了很多动态组件:

this.factory = this.componentFactoryResolver.resolveComponentFactory(SliderComponent);
this.sliderComponentReference = viewContainerRef.createComponent(this.factory);

当我需要销毁组件时,我调用 destroy 方法:

this.sliderComponentReference.destroy();

我知道它从视图中删除了动态组件并且它是实例但是当我在我注意到它仍然有信息之后立即查看变量时:

changeDetectorRef: ViewRef_ _view: …, _viewContainerRef: ViewContainerRef.. 
componentType:(...)
hostView: ViewRef_ _view: …, _viewContainerRef: ViewContainerRef... 
injector:(...)

问题:

    如果变量被销毁了,怎么还有对组件实例的引用?

    组件是否仍存储在内存中?如果可以,是否可以检索?

【问题讨论】:

“查看变量之后”是指this.sliderRef.destroy(); console.log(this.sliderRef)? 我创建了这个StackBlitz Demo,所以任何有兴趣的人都可以看到 OP 所指内容的运行代码示例。 【参考方案1】:

您可以在此处查看组件引用定义:https://github.com/angular/angular/blob/master/packages/core/src/view/refs.ts#L103 -- 它具有changeDetectorRefhostView 等属性。当你调用.destroy时,它会调用底层的viewRef.destroy方法:https://github.com/angular/angular/blob/master/packages/core/src/view/refs.ts#L277

这最终会调用其他方法,但它似乎并没有真正覆盖组件 ref 上已经定义的任何属性。据我所知,在 javascript 中,对象不能自行删除。您只能删除引用该对象的对象的属性。

组件仍然存储在内存中,并且在某种意义上仍然可以使用。但是,由于.destroy 的作用,它可能无法按您的预期工作。不过,您也许可以重新创建它……而且还有attach 方法。 JavaScript 进行自己的垃圾收集/内存管理,因此您不能真正强制将这些元素从内存中删除。如果 JavaScript 在垃圾回收周期中检测到 ref 不再可以被任何指针访问,它将释放该内存。

【讨论】:

让 componentRef = this.componentFactoryResolver.resolveComponentFactory(cmptName).create(this.injector);this.dynamicComponentContainer.insert(componentRef.hostView);我将 componentRef 保存在数组中,比如“componentTracker”变量,我们在 DOM 中有 3 个组件。我们是否可以使用存储在“componentTracker”中的参考来销毁特定组件,即 this.componentTracker[i].destroy();

以上是关于Angular完全销毁动态创建的组件的主要内容,如果未能解决你的问题,请参考以下文章

Angular2动态组件和TP jQuery库

如何在没有 ComponentFactory 的情况下销毁 Angular 2 组件?

在 Angular 中动态创建的嵌套组件

Angular获取动态创建的组件的viewContainerRef

子动态创建的组件与父组件之间的Angular4通信

Angular 7 - 向动态创建的组件添加拖放行为