共计 3176 个字符,预计需要花费 8 分钟才能阅读完成。
本文会蕴含作者一些了解,为了不和原作者意思混同,会将集体的了解放在【】里。
原文地址
那是我忙于为我的办公我的项目创作新性能的日子之一。忽然间,某些事件引起了我的留神。
上图是 angular 最终渲染进去的 DOM
当我审查 DOM 时候,我看到这个 ngcontent
被 Angular 利用到了元素上。如果他们蕴含元素在最终的 DOM 里,那么 <ng-container>
是用来干什么的?那是我很困惑在 <ng-container>
和 <ng-content>
中。
在探寻问题答案的时候我发现了 <ng-template>
和 *ngTemplateOutlet
的概念。当初咱们有四个听起来简直雷同的概念。我开始了探寻它们的旅程。
你已经也遇到过这种状况吗?如果是,那么你来对中央了。闲话少说,让咱们一个一个来解说他们。
1. < ng-template >
顾名思义,<ng-template>
是一个模板元素,用于 Angular 与构造指令联合应用 (*ngIf
, *ngFor
, [ngSwitch]
和自定义指令)
<font color=’red’> 这些模板元素仅工作在构造指令存在的时候 </font>。Angular 包装了咱们利用指令的元素。思考下边的一个 *ngIf
的例子。
【咱们能够看到,在一个一般元素上增加构造指令,angular 在解析时候,其实会帮我买创立一个 ng-template 元素,并将相干的构造指令放到 ng-template 上进行解决】
下面展现的是 Angular 对与 *ngIf
的解释。最终的 DOM 与咱们在本文结尾看到的相似。
应用办法
咱们曾经看到了 Angular 应用 <ng-template>
的形式。然而咱们如何应用它呢?因为它只和构造指令一起工作,所以咱们能够这样应用:【这种是❌形式,后边会讲到】
此处的 home
设置为 true
,上述代码在 DOM 中的输入为:
什么都没有被渲染进去!这是为什么呢?其实,这正是预期的后果。正如咱们曾经探讨过的,Angular 会用正文代替ng-template
【译文应用的 Angular 版本为 6.1.10。在 Angular12 版本,曾经用非凡的 className 代替正文了】,咱们的代码最终会被解释成如下代码。
咱们的 <ng-template>
在被 Angular 包装之后,变成了两个。然而无论怎样,Angular 都不对 <ng-template>
的内容进行选中。
以下是两种 <font color=green> 正确 </font> 的应用形式:
Method 1
在第一种办法中,你提供给 Angular 一种不须要进一步解决的形式。这样 Angular 将仅仅转换 <ng-template>
到正文里,并不会扭转其内容。(它们不会再像之前的例子一样被放在任何 <ng-template>
中)。因而,它将正确的渲染内容。
要想理解更多如何应用此构造和更多的构造指令,请参考这篇文章。
Method2
这是一种很少应用的形式(应用两个<ng-template>
)。这里咱们在 then 中给出了一个模板援用,通知他当条件为真时候应该渲染什么。
像这样应用多 <ng-template>
(你能够应用<ng-container>
代替)是不被倡议的因为这不是 Angular 的本意。<ng-template>
该当被应用在多处重复使用的场景下。咱们将在文章前面的局部更具体的探讨。
< ng-container >
你是否已经写过或看到过相似这样的代码
咱们大部分人写这样代码的起因在于 Angular 无奈再单个元素上应用多个构造指令。当初这个代码失常工作,然而如果 item.id 为 false,它就会在 dom 中引入很多空的<div>
在简略的例子中可能不须要关怀它,但如果在大型简单的利用中时候(会展现成千上万的数据),它可能变得麻烦,因为有可能会有监听器在这些 DOM 上。
更蹩脚的是你可能必须去嵌套你的 CSS。【大略是想表白这些写会在附加款式时候须要额定的选择器】
不要放心!咱们有 <ng-container>
能够解决。
<ng-container>
是一个组元素,它不会烦扰款式或布局,因为 Angular 不会将它们渲染到 DOM 中。
以上代码会渲染出这样的 DOM 构造
看,咱们解脱了那些空的 div。咱们应该应用 <ng-container>
当咱们仅仅想应用多个构造指令而不想引入多的 DOM 时候。
3、< ng-content >
它用于创立可配置的组件。这意味着组件能够依据用户的志愿来配置。这就是家喻户晓的内容投影~
思考一个简略的应用了 <ng-content>
的组件
在 <project-content>
组件的开始标记和完结标记之间是将要被内容投影的内容。【也就是 vue 和 react 的 slot】
这些内容将被渲染在组件的 <ng-content>
中,这将容许自定义 <project-content>
组件的页脚局部。
多重投影
如果你能够决定哪些内容能够被渲染到哪些地方会怎么?您还能够应用 <ng-content>
的 select 属性来管制内容的投影形式,而不是在单个的 <ng-content>
中投影每个内容。它须要一个元素选择器来决定特定的 <ng-content>
中投影哪些内容.
办法如下:
咱们批改 <project-content>
来演示如何应用多内容投影。Select 属性选择器将在特定的 <ng-content>
中出现的内容。这里咱们首先抉择出现 h1 元素,如果投射的内容中没有 h1 元素,它将不会渲染任何内容。同样,第二个抉择查找 div。其余的内容在最初一个 <ng-content>
中出现。
以上的形式应该是老版本的 Angular 了,当初的 Angular 文档中没有提到,当初的应用形式请查看最新文档
4、*ngTemplateOutlet
*ngTemplateOutlet
个别被用在两个场景:
- 不管循环或条件如何,在视图中插入一个公共模板
- 创立一个高度配置的组件
模版重用
思考一个视图,其必须在多个地位插入模板。例如,要搁置在网站中的公司 logo。咱们能够通过为 logo 编写一次模板并在视图的任何中央重用来实现它。
上面是代码片段:
正如你看到的,咱们只写了一次模板代码,并应用了它三次!
<*ngTemplateOutlet>
也承受一个上下文对象,能够传递改对象来自定义通用模板输入。无关上下文的更多信息,请参阅官网文档
自定义组件
<*ngTemplateOutlet>
的第二个应用形式是高度订制组件。思考咱们之前的<project-content>
的示例。并进行一些批改。
下面是<project-content>
组件的批改版本,它承受三个属性 —— <headerTemplate>
<bodyTemplate>
<footerTemplate>
。上面是其代码片段:
咱们在这里视图实现的是显示从 <project-content>
的父组件承受到的页眉,注释和页脚。如果其中任何一个未提供,咱们的组件在其地位展现默认模版。因而,创立了一个高度订制的组件。
当初应用咱们刚创立的组件:
这是咱们如何传递一个 template refs 给咱们的组件的形式。如果其中任何一个没有传递,组件将渲染默认的模板!
ng-content vs *ngTemplateOutlet
它们都帮咱们实现了高度自定义的组件,然而咱们该如何抉择它们呢?
能够革除的看到,*ngTemplateOutlet
给了咱们更多的能力,例如提供默认的模板 …
但 <ng-content>
智能依照原样出现内容,借助 select 属性,您能够拆分内容并在视图的不同地位出现它们。您不能有条件的出现 <ng-content>
的内容。您必须限度从父组件哪里承受到的内容,而无奈依据内容做出决定。
无论如何,在这两个间进行抉择齐全取决于你的用例。至多当初咱们有了一个新的武器 *ngTemplateOutlet
,它提供了更多的控制权比照<ng-content>