<ng-container>与<template>的区别

191
<ng-container>是在官方文档中提到的,但我仍在努力理解它的工作原理和用途。

尤其是在ngPluralngSwitch指令中进行了特别提及。

<ng-container>是否与<template>执行相同的操作,或者是否取决于编写指令时使用其中之一?

是什么呢?

<ng-container *ngPluralCase="'=0'">there is nothing</ng-container>

<template [ngPluralCase]="'=0'">there is nothing</template>

这两个应该是相同的吗?

我们如何选择其中一个?

<ng-container> 如何在自定义指令中使用?

6个回答

309

编辑:现在已经文档化

<ng-container> to the rescue

The Angular <ng-container> is a grouping element that doesn't interfere with styles or layout because Angular doesn't put it in the DOM.

(...)

The <ng-container> is a syntax element recognized by the Angular parser. It's not a directive, component, class, or interface. It's more like the curly braces in a JavaScript if-block:

  if (someCondition) {
     statement1; 
     statement2;
     statement3;
    }

Without those braces, JavaScript would only execute the first statement when you intend to conditionally execute all of them as a single block. The <ng-container> satisfies a similar need in Angular templates.

原始回答:

根据这个拉取请求:

<ng-container>是一个逻辑容器,可用于分组节点,但不作为节点在DOM树中呈现。

<ng-container>呈现为HTML注释。

因此,这个Angular模板:

<div>
    <ng-container>foo</ng-container>
<div>

将产生这种输出:

<div>
    <!--template bindings={}-->foo
<div>

所以,当您想要在应用程序中有条件地附加一组元素(即使用*ngIf="foo")但不想用另一个元素包装它们时,ng-container非常有用。
<div>
    <ng-container *ngIf="true">
        <h2>Title</h2>
        <div>Content</div>
    </ng-container>
</div>

将会产生:

<div>
    <h2>Title</h2>
    <div>Content</div>
</div>

这是一个很好的观点。我猜当<template>没有指令时,它与之不同。在这种情况下,<template>只会产生<!--template bindings={}--> - Estus Flask
实际上,<template></template>将生成<script></script>请参阅此处 - n00dl3
在我的情况下并非如此。即使在编译期间存在<script>,它也会在之后被移除,在DOM中没有额外的标签。我相信该手册包含已弃用的信息或者是错误的。无论如何,感谢您指出了<ng-container>和<template>之间的主要区别。 - Estus Flask
在发布之前,Angular 渲染 <script></script>。相当一段时间以来,它一直渲染类似于 <!--template bindings={}--> 的东西。文档很快就会修复。 - Ward
1
文档中不再包含说明。我尝试查找关于 ng-container 的文档页面,但没有找到任何内容。它是否已被弃用?为什么没有文档记录? - Olivier Boissé

49

文档(https://angular.io/guide/template-syntax#!#star-template)给出以下示例。假设我们有这样的模板代码:

<hero-detail *ngIf="currentHero" [hero]="currentHero"></hero-detail>
在渲染之前,它将被"去糖化"。也就是说,星号符号将被转录为代码符号:*
<template [ngIf]="currentHero">
  <hero-detail [hero]="currentHero"></hero-detail>
</template>
如果'currentHero'的值为真,那么它将被呈现为
<hero-detail> [...] </hero-detail>

但是如果你想要类似这样的条件输出:

<h1>Title</h1><br>
<p>text</p>

...而且您不希望输出被包装在容器中。

您可以直接编写未压缩版本,如下所示:

<template [ngIf]="showContent">
  <h1>Title</h1>
  <p>text</p><br>
</template>

这将完美地起作用。然而,现在我们需要使用方括号[]而不是星号*来使用ngIf,这有些令人困惑(https://github.com/angular/angular.io/issues/2303)

因此,创建了一种不同的符号表示方法,如下所示:

<ng-container *ngIf="showContent"><br>
  <h1>Title</h1><br>
  <p>text</p><br>
</ng-container>

两个版本将产生相同的结果(只呈现h1和p标签)。第二个版本更受欢迎,因为你可以像往常一样使用*ngIf。


很好的解释,它提供了关于“ng-container指令思想是如何产生”的概述,谢谢 :) - Pankaj Parkar

1

就行为而言,这种情况

<template [ngIf]="show">
  <h1></h1>
  <p></p>
</template>

等同于

<ng-container *ngIf="show">
  <h1></h1>
  <p></p>
</ng-container>

那么,应该使用哪一个呢?
首选ng-container,因为这样我们保留了结构指令用星号表示的惯例,例如*ngIf*ngFor等。
然而,在某些情况下,我们必须使用template。例如,在需要通过模板名称引用template标记的情况下,如<template #templateName>
有关更详细的答案,请参见https://dev59.com/SVkS5IYBdhLWcg3ws4gk#40762236

0

ng-container 的使用场景通常是简单替换,而自定义模板/组件则会过度设计。在 API 文档中,他们提到了以下内容:

使用 ng-container 来分组多个根节点

我想这就是它的全部意义:分组。

请注意,ng-container 指令会被取消,而不是像模板那样将其指令包装在实际内容周围。


1
https://angular.io/docs/ts/latest/api/common/index/NgSwitch-directive.html - Jan B.
1
谢谢,我在文档网站上创建了一个关于缺乏文档的问题,并引用了这个答案:https://github.com/angular/angular.io/issues/2553 - Koslun
答案并不清楚<template>与其相同的作用有何区别。顺便说一下,我可以使用<template ngPluralCase="=0">使ngPluralCase起作用。但是在问题中提到的方式在最终版本中会给我带来Can't bind to 'ngPluralCase' since it isn't a known property of 'ng-container'的错误。不确定这意味着什么。 - Estus Flask
1
被踩了-1。ng-container 不是为了避免自定义模板,而是为了能够拥有不包含在容器中的条件内容。事实上,自定义模板也会引入一个包装容器,即指令标签本身。 - Carlo Roosen
1
你说得完全正确。这确实是需要提到的一个区别。我已经在我的帖子中添加了提示。 - Jan B.
显示剩余2条评论

0
在我的情况下,它的作用类似于 <div><span>,但是即使是 <span> 也会影响我的 AngularFlex 样式,但是 ng-container 不会。

-1
一个使用场景是当你想要在带有 *ngIf 和 *ngFor 的表格中使用它 - 因为将 div 放在 td/th 中会导致表格元素 出现问题。我曾经遇到过这个问题,而那个就是答案。

1
但是使用<template [ngIf]...>也可以实现相同的效果。问题在于这两种方法之间的区别。 - Estus Flask
哦,我的错,似乎这里已经有答案了:https://dev59.com/a1kR5IYBdhLWcg3w_CD- 他们只是说这只是语法上的区别。 - shakram02

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接