ViewContainerRef的remove()和ComponentRef的destroy()有什么区别?

时间:2019-11-06 03:21:45

标签: angular typescript

我知道ViewContainerRef的remove()会破坏关联的视图,因此定义它的组件也会被破坏吗? ComponentRef的destroy()与ViewContainerRef的remove()之间有什么区别,何时应该在另一个之上使用?

例如,在这里我正在动态创建和显示子组件。

@ViewChild('taskView', {static: true, read: ViewContainerRef}) vc: ViewContainerRef;

compRef : ComponentRef;

constructor(private CFR: ComponentFactoryResolver){ }

ngOnInit() {
  const factory=this.CFR.resolveComponentFactory(TaskItemComponent);
  const componentRef=this.vc.createComponent(factory);
  this.compRef= componentRef;
}


我意识到我可以通过两种方式删除此动态添加的组件,或者使用ViewContainerRef的remove破坏视图,就像这样:

let vcrIndex: number = this.VCR.indexOf(this.compRef)
this.VCR.remove(vcrIndex);

或者通过像这样破坏组件实例本身:

this.compRef.destroy();

我的应用程序中的效果是相同的。但是两者之间有什么区别?我也对此早期的堆栈溢出帖子感到困惑: Does ViewContainerRef.clear() remove component from memory?

投票得最高的答案写道

No, if you assign parent component property to componentRef angular won't remove component from memory.

Angular only destroys component and removes its own references to this component. But reference to componentRef remains to live in your component property. So i would assign null to it. This way garbage collect will be able to clear memory"

这是否意味着即使在我的componentRef上调用destroy()之后,我的componentRef仍指向被破坏的实例?调用destroy()或remove()时,内存中发生了什么?

1 个答案:

答案 0 :(得分:1)

MDN documentation所述

  

垃圾收集算法所依赖的主要概念是   参考的概念。 ...为了释放对象的内存,它   需要明确使其无法访问。

这意味着,如果您有引用您组件的内容,那么它将仍然存在于内存中。

  

这是否意味着即使在我的componentRef上调用destroy()之后   我的componentRef仍指向被破坏的实例?

在您破坏保留componentRef属性的类(或服务)之前,它仍将指向被破坏的实例。如果您销毁了组件,但是您的类(正在使用动态组件的类)将在那之后存活,那么最好将componentRef属性分配给null

关于区别,他们在做相同的事情:

ComponentRef.destroy()

destroy() {
   if (this._appRef) {
     this._appRef.detachView(this);
   } else if (this._viewContainerRef) {
     // does detachEmbeddedView internally
     this._viewContainerRef.detach(this._viewContainerRef.indexOf(this)); 
   }
   Services.destroyView(this._view);
 }

ViewContainerRef.remove

remove(index?: number): void {
  const viewData = detachEmbeddedView(this._data, index);
  if (viewData) {
    Services.destroyView(viewData);
  }
}