乐趣区

关于angular:ngtemplate-ngcontent-ngcontainer-和-ngTemplateOutlet的区别

原文

明天当我在做 Angular 开发时,一个知识点引起了我的留神:

在查看 DOM 时,我看到 ngcontent 被 Angular 利用于元素。嗯……如果它们蕴含了最终 DOM 中的元素,那么 \<ng-container> 有什么用?过后我对 \<ng-container> 和 \<ng-content> 的区别感到困惑。

在寻求晓得我的问题的答案的过程中,我发现了 \<ng-template> 的概念。令我诧异的是,还有另一个容易混同的概念:*ngTemplateOutlet。我开始了我的旅程,寻求对两个概念的廓清,但当初我有四个,听起来简直一样!

你遇到过这种状况吗?如果是,那么您来对中央了。因而,事不宜迟,让咱们一一介绍。

1. \<ng-template>

顾名思义,\<ng-template> 是一个模板元素,Angular 与构造指令(ngIf、ngFor、[ngSwitch] 和自定义指令)一起应用。

这些模板元素仅在存在构造指令时才起作用。Angular 将宿主元素(指令所利用到的元素)包装在 \<ng-template> 中,并通过用诊断正文 (diagnostic comments) 替换它来应用实现的 DOM 中的 \<ng-template>。

思考一个简略的 *ngIf 示例:

下面显示的是 *ngIf 的 Angular 解释,也就是解除语法糖之后的理论代码。Angular 将利用指令的宿主元素放在 \<ng-template> 中,并放弃宿主原样。最终的 DOM 相似于咱们在本文结尾看到的:

2. \<ng-container>

咱们很多人编写这段代码的起因是无奈在 Angular 中的单个宿主元素上应用多个构造指令。当初这段代码工作失常,但如果 item.id 是一个可能不须要的虚伪值,它会在 DOM 中引入几个额定的空 \<div>。

人们可能不会关怀像这样的简略示例,然而对于具备简单 DOM(显示数万个数据)的大型应用程序,这可能会变得很麻烦,因为元素可能具备附加到它们的侦听器,这些侦听器依然存在于 DOM 监听事件。

更蹩脚的是利用款式 (CSS) 必须执行的嵌套级别!

不必放心,咱们有 \<ng-container> 来救济!

Angular \<ng-container> 是一个不会烦扰款式或布局的分组元素,因为 Angular 不会将它放在 DOM 中。

应用 ng-container 重写。

能够了解成把 div 标签搁置到 ng-container 这个虚无的容器里,当 div 的 *ngIf 指令布尔值为 false 时,虚无的容器连同外面的 div 标签压根就不会生成。

最初渲染出的 HTML 代码里,没有多余的空 div 标签了:

最佳实际:当咱们只想利用多个构造指令而不在咱们的 DOM 中引入任何额定元素时,咱们应该应用 \<ng-container>。

3. \<ng-content>

它们用于创立可配置组件。这意味着能够依据用户的须要配置组件。这就是家喻户晓的内容投影: Content Projection. 已公布库中应用的组件应用 \<ng-content> 使本人可配置。

思考一个简略的 \<project-content> 组件,下图是其自身的 HTML 定义:

显然,footer 区域容许动静配置内容。

下图展现了如何为 footer 区域动静注入自定义 footer 内容。这种用法称为繁多投射。

\<project-content> 组件的开始和完结标记中传递的 HTML 内容就是要投影的内容。这就是咱们所说的内容投影。内容将在提供内容投影性能组件内的 \<ng-content> 内出现。

这容许 \<project-content> 组件的使用者在组件内传递任何自定义页脚并精确管制他们心愿如何出现它。

Multiple Projections

如果您能够决定哪些内容应该放在什么中央呢?除了将每个内容投影到单个 \<ng-content> 中之外,您还能够应用 \<ng-content> 的 select 属性管制内容的投影形式。它须要一个元素选择器来决定在特定的 \<ng-content> 中投射哪些内容。

就是这样:

咱们批改了 \<project-content> 定义以执行多内容投影。select 属性抉择将在特定 <ng-content> 中出现的内容类型。这里咱们首先抉择渲染题目 h1 元素。如果投影内容没有 h1 元素,它将不会出现任何内容。同样,第二个抉择查找 div。其余内容在最初一个 \<ng-content> 中出现,没有抉择。

如何生产这个带有 select 属性的,容许多重投射的组件?办法如下所示:

4. *ngTemplateOutlet

*ngTemplateOutlet 用于两种场景:

  • 在视图的各个局部插入一个通用模板,而不思考循环或条件
  • 制作高度配置的组件。

模板重用

思考一个视图,您必须在多个地位插入模板。例如,要搁置在网站中的公司徽标。咱们能够通过为徽标编写一次模板并在视图中的任何中央重用它来实现它。

以下是代码片段:

如您所见,咱们只编写了一次徽标模板,并在同一页面上应用一行代码将其应用了 3 次!

Customizable components

*ngTemplateOutlet 的第二个用例是高度定制的组件。思考咱们之前的 \<project-content> 组件示例,并进行了一些批改:

以上是 \<project-content> 组件的批改版本,它承受三个输出属性 —— headerTemplate、bodyTemplate、footerTemplate。以下是 project-content.ts 的片段:

模板文件里应用到的 input 属性,headerTemplate,bodyTemplate 和 footerTemplate 属性定义在 Component 文件里。

咱们在这里试图实现的是显示从 \<project-content> 的父组件接管到的页眉、注释和页脚。如果未提供其中任何一个,咱们的组件将在其地位显示默认模板。因而,创立了一个高度定制的组件。

要应用咱们最近批改的组件:

这就是咱们将模板援用传递给咱们的组件的形式。如果其中任何一个未通过,则组件将出现默认模板。

ng-content vs. *ngTemplateOutlet

它们都能够帮忙咱们实现高度定制化的组件,但抉择哪个以及何时抉择?

能够分明地看到,如果没有提供,*ngTemplateOutlet 为咱们提供了更多显示 默认模板 的能力。

这不是 ng-content 的状况。它按原样出现内容。您最多能够在 select 属性的帮忙下拆分内容并在视图的不同地位出现它们。您不能有条件地出现 ng-content 中的内容。您必须显示从父级收到的内容,而无奈依据内容做出决定。

然而,在两者中进行抉择齐全取决于您的用例。至多当初咱们的武器库中有一个新武器 *ngTemplateOutlet,除了 ng-content 的性能外,它还提供了对内容的更多管制!

更多 Jerry 的原创文章,尽在:” 汪子熙 ”:

退出移动版