Angular: 从组件引用 EmbeddedViewRef

Angular: referencing EmbeddedViewRef from a component

EmbeddedViewRef 上引用 Angular 核心 API 文档页面:

An embedded view can be referenced from a component other than the hosting component whose template defines it, or it can be defined independently by a TemplateRef.

我很清楚,对于后者,我可以从 TemplateRef 实例创建一个 EmbeddedViewRef 实例,例如,

example.component.html

<p>Hip!</p>
<ng-container #vc></ng-container>
<ng-template #tpl>
  <p>Hip!</p>
</ng-template>
<p>Hooray!</p>

example.component.ts

ngAfterViewInit() {
  const embeddedView = this.tpl.createEmbeddedView(null);
  this.vc.insert(embeddedView);
}

但它仍然给我留下了一个关于前者的悬而未决的问题:我们如何从模板定义它的托管组件以外的组件引用嵌入式视图?

An embedded view can be referenced from a component other than the hosting component whose template defines it, or it can be defined independently by a TemplateRef.

它们指的是模板中 this 的值。

当你写一个像 <h1>{{value}}</h1> 这样的表达式时,它引用了当前组件上名为 value 的 属性。我们不使用 this 作为表达式的前缀,例如 <h1>{{this.value}}</h1> 因为 context 始终是组件。

因此,当您从模板引用创建嵌入视图时。模板源自的组件一直是 this 的上下文。这就是他们所说的 "can be referenced from a component other than the hosting component" 的意思。视图附加到另一个组件的视图容器这一事实不会更改模板中 this 的值。

这是关于嵌入式视图的一个重要事实,文档中没有明确解释。当您将嵌入式视图附加到 another 组件的视图容器时,该嵌入式视图将遵循该 other 组件的生命周期。这意味着,如果创建嵌入视图的原始组件是 destroyed,那么嵌入视图将继续引用 this 的值,它现在是一个被破坏的组件。

您可以通过在创建嵌入式视图的组件也被销毁时销毁嵌入式视图来解决这个问题。

我创建了一个 stackblitz 来说明这个问题。 "child" 组件创建一个嵌入式视图,并将其附加到父组件的视图容器。嵌入式视图引用子项的属性并调用方法。这是从另一个组件的视图发生的,说明 this 的值没有改变,但是当 "child" 被销毁时,我也必须销毁嵌入视图。

https://stackblitz.com/edit/angular-eg4vpf

现在,回到 stackblitz 并注释掉 child.component.ts 中的第 27 行,这样视图就不会被破坏。查看应用程序清除后模板引用如何继续引用 this,但创建这些模板的组件已被销毁。那将是应用程序中的错误。