什么是 ng-template 以及为什么我要将 *ngIf then else 绑定到它?

What is ng-template and why do I bind *ngIf then else to it?

当我将 *ngIf 与 then and/or else 语句一起使用时,为什么我必须绑定到附加到 ng-template 元素的模板变量?例如:

这个有效:

<div *ngIf="show; else elseBlock">Text to show</div>
<ng-template #elseBlock>Alternate text while primary text is hidden</ng-template>

但这不起作用:

<div *ngIf="show; else elseBlock">Text to show</div>
<div #elseBlock>Alternate text while primary text is hidden</div>

我还注意到添加 class 也不起作用:

<ng-template #elseBlock class="my-class">
  Alternate text while primary text is hidden
</ng-template>

ng-template 有什么特别之处?有什么不同?

ng-template 是 Angular 实现和扩展 template 标签的方式。

由于所有以 * 开头的结构指令,如 *ngIf、*ngFor 等,都在改变 DOM 它实际上一直在幕后使用 ng-template。放置在元素上的指令只是对此的一些语法糖。

else 块不适用于任何其他元素,因为它需要在需要时添加,所以它必须在 ng-template 中。

Here 是关于此的更多信息。

这是 class 的部分答案。但是也可以在一个地方链接到相关信息。 我可以给你一些关于另一个类似概念的细节。 <ng-template> 是一个占位符,不仅用于 *ngIf, but also in *NgFor

的 else 部分

<ng-container> 是类似的东西,你没有问过,但是你稍后在处理内容投影时会遇到。 video Josh Morony 在 Youtube 上发表了一篇关于此的文章。它与@ContentChild 和@ContentChildren 有关。

Angular Cheatsheet 告诉你 class..

的语法

<ng-template> 当您想根据条件及其相反显示或隐藏模板的一部分时,'handy' 非常有用。 在你的例子中:

<div *ngIf="show; else elseBlock">Text to show</div>
<ng-template #elseBlock>Alternate text while primary text is hidden</ng-template>

它可以让你做你本可以做的事情:

<div *ngIf="show">Text to show</div>
<div *ngIf="!show>Alternate text while primary text is hidden</div>

的优点是您可以隔离部分模板并在需要时'activate'它,就像 plein 对 JS 所做的那样。你可以不总是把它放在后面。它为您提供了更结构化的代码。 还有(因为Angular4.3我觉得)<..*ngIf="condition"; then #template1 else #template2>也很'handy'.

这是因为 Angular 中的所有结构指令都会创建嵌入式视图。嵌入式视图是使用 templateRefviewContainerRef 创建的。您可以在 Exploring Angular DOM manipulation techniques using ViewContainerRef.

中阅读更多关于它们的信息

嵌入式视图类似于为组件创建的宿主视图。视图包含您在组件模板中或 ng-template 标记内看到的所有节点。所以嵌入式视图就像一个没有组件 class 的组件模板。以下是结构指令如何创建嵌入式视图的几个示例。

ngIf

  private _updateView() {
    if (this._context.$implicit) {
      ...
        if (this._thenTemplateRef) {
          this._thenViewRef =
              // here embedded view is created
              this._viewContainer.createEmbeddedView(this._thenTemplateRef, this._context);
        }
      }
    } else {
      if (!this._elseViewRef) {
       ...
          this._elseViewRef =
              // here embedded view is created
              this._viewContainer.createEmbeddedView(this._elseTemplateRef, this._context);
        }
      }
    }
  }

ngFor

  private _applyChanges(changes: IterableChanges<T>) {
    const insertTuples: RecordViewTuple<T>[] = [];
    changes.forEachOperation(
        (item: IterableChangeRecord<any>, adjustedPreviousIndex: number, currentIndex: number) => {
          if (item.previousIndex == null) {
            // here embedded view is created
            const view = this._viewContainer.createEmbeddedView(
                this._template, new NgForOfContext<T>(null !, this.ngForOf, -1, -1), currentIndex);