原文

今天当我在做 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 属性选择将在特定 中呈现的内容类型。 这里我们首先选择渲染标题 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的原创文章,尽在:“汪子熙”:

一文了解 ng-template, ng-content, ng-container, 和 *ngTemplateOutlet的区别相关推荐

  1. Python中request的content,text和string方法的区别

    content,text和string方法的区别 content & text text & string content & text 源码: @propertydef te ...

  2. 一文搞懂BN、LN、IN、GN的区别

    一文搞懂BN.LN.IN.GN的区别 批归一化(BN)已经成为许多先进深度学习模型的重要组成部分,特别是在计算机视觉领域.它通过批处理中计算的平均值和方差来规范化层输入,因此得名.要使BN工作,批大小 ...

  3. 文网文是什么?与ICP和EDI许可证有什么区别?

    很多人不懂文网文是什么,ICP和EDI许可证又有什么区别.今天小编给大家简单的科普一下什么是文网文.ICP.EDI经营许可证,以及它们有什么作用,让想进行互联网开发的你们对此有一定的认识. 文网文 文 ...

  4. cannot bind to cxOutlet since it is not a known property of ng template

    我在SAP Spartacus处于运行状态(即ng serve)始终处于运行状态时,进行代码热修改,经常遇到此类错误消息 退出ng serve,重新执行即可: 更多Jerry的原创文章,尽在:&quo ...

  5. ng build --aot 与 ng build --prod

    angluar的编译有以下几种方式: ng build  常规的压缩操作    代码体积最大 ng build --aot   angular预编译      代码体积较小 ng build --pr ...

  6. Qt文档阅读笔记-WebEngine Content Manipulatoin Example

    这个例子展示了如何使用Qt WebEngine Widgets创建一个web浏览器,并且如何使用JQuery去修改web浏览器中的内容. 调用QWebEnginePage::runJavaScript ...

  7. 一文看懂 Bahdanau 和 Luong 两种 Attention 机制的区别

    来自 | 知乎  作者 | Flitter 链接 | https://zhuanlan.zhihu.com/p/129316415 编辑 | 深度学习这件小事公众号 本文仅作学术交流,如有侵权,请联系 ...

  8. 一文读懂“个人经营收款码”和“个人收款码”的区别

    目前有90%的普通网民误读了"个人收款码"只需简单升级就是"个人经营收款码",使用方式和之前的不变,仍然免费收款.商家们更是大夸两大巨头良心满满.今天小编就一文 ...

  9. 一文弄懂Hive中谓词下推(on与where的区别)

    文章目录 场景模拟 问题描述 Hive谓词下推 谓词下推概念 PPD 配置 基本概念 官网解释 规则总结 规则表 特殊说明 结论 场景模拟 数仓实际开发中经常会涉及到多表关联,这个时候就会涉及到on与 ...

最新文章

  1. python字典去重
  2. Webpack 学习记录-02
  3. 下载r包IlluminaHumanMethylation450kanno.ilmn12.hg19
  4. 微信小程序开发--如何在swiper中显示两个item以及下一个item的部分内容
  5. 前些天做的一个物联网架构三层扩展
  6. Matlab:成功解决Index must be a positive integer or logical
  7. 从Web借鉴UI设计
  8. 斯特林反演[bzoj4671]异或图
  9. 对刺客历史的一种颠覆:说说《最后的刺客》
  10. asp.net core AuthenticationMiddleware 在WebApi中的的使用
  11. 戴尔新版bios设置中文_戴尔电脑装机过程
  12. python安装包找不到setup_如何安装没有setup.py的Python模块?
  13. JavaScript 面向对象编程(二) —— 构造函数 / 原型 / 继承 / ES5 新增方法
  14. Elasticsearch Scale Out
  15. 虚拟资源拳王公社:什么都不会做什么副业赚钱?最容易上手的兼职副业是什么
  16. mysql内置时间函数大全_MySQL 的时间函数 大全
  17. linux命令行发送串口_从命令行在Linux中发送电子邮件
  18. Caffe︱构建lmdb数据集、binaryproto均值文件及各类难辨的文件路径名设置细解
  19. ECharts3使用入门
  20. pom.xml 注释

热门文章

  1. 产品经理如何基于需求迭代产品(下篇3):产品的整体设计之逻辑层和交互层...
  2. USACO SECTION 1.1.2 Transformations 爆搜
  3. 使用思科模拟器Packet Tracer与GNS3配置IPv6隧道
  4. 收集 | 方便实用的在线网站
  5. 11、1.4.3 测试JDK安装成功
  6. linux安装redis集群+常见报错
  7. centos7添加新网卡实现双IP双网关
  8. Echarts 自定义数据视图
  9. C#开发纽曼来电小秘书总结(指南)
  10. 非mapreduce生成Hfile,然后导入hbase当中