ng-template、ng-content、ng-container

ng-template、ng-content、ng-container

一、ng-template

ng-template 是 Angular 结构型指令中的一种,用于定义模板渲染 HTML(模板加载)。定义的模板不会直接显示出来,需要通过其他结构型指令(如 ng-if)或 template-ref 将模块内容渲染到页面中。

1
2
3
4
<div *ngIf="show else xxxx">控制ng-template是否显示和隐藏</div>
<ng-template #xxxx>
ng-template中的内容显示和隐藏,通过结构性指令*ngif来控制,当ngif为false,这显示
</ng-template>

二、ng-container

  • ng-container 既不是一个 Component 组件,也不是一个 Directive 指令,只是单纯的一个特殊 tag 标签。ng-container 可以直接包裹任何元素,包括文本,但本身不会生成元素标签,也不会影响页面样式和布局。包裹的内容,如果不通过其他指令控制,会直接渲染到页面中。
  • 可以把 ng-container 简单理解为一个逻辑容器。用来做一些逻辑处理的。减少不必要的 html 标签。
  • sng-container 有一个用处就是配合 ngFor 和 ngIf 使用。我们知道 ngFor 和 ngIf 不能同时处在同一个元素上。
1
2
3
4
5
<ul>
<ng-container *ngFor="let item of arr">
<li *ngIf="item % 2 === 0">{{item}}</li>
</ng-container>
</ul>

三、ng-content 插槽

  • 在实际的使用中,我们会用到内容投影,即插槽的概念。在 vue 中可以通过 slot 来标记插槽,从而达到从父组件向子组件传递显示内容。
  • 在 angular 中,同样可以使用 ng-content 来实现与 vue 中的 slot 同样的功能和效果。

简单投影(单个插槽| 默认插槽| 匿名插槽)

1
2
3
4
5
<app-slot>
<h2>我是嵌入的外部内容,相当于vue的slot</h2>
<p>我是ng content 内容投影</p>
<span>ng content测试</span>
</app-slot>
1
2
3
<div>
<ng-content></ng-content>
</div>

针对性投影(具名插槽)

针对性投影,相当于 vue 中 slot 的 name 属性和组件的 slot 属性的映射关系

1
2
3
4
5
<app-slot>
<h2 class="slot">我是嵌入的外部内容,相当于vue的slot</h2>
<p>我是ng content 内容投影</p>
<span>ng content测试</span>
</app-slot>
1
2
3
4
5
6
7
<div>
<ng-content select="p"></ng-content>
<hr />
<ng-content select=".slot"></ng-content>
<hr />
<ng-content></ng-content>
</div>

ngProjectAs

  • 通过 ng-content 的 select 属性可以指定 html 标签或者组件投射 ng-content 位置上来。但是呢有个限制条件。不管是 select 标签或者组件的名字、或者 class、或者是属性他们都是作用在直接子节点上。
  • 有时你的内部组件会被隐藏在另一个更大的组件中。有时你只需要将其包装在额外的容器中即可应用 ngIf 或 ngSwitch。无论什么原因,通常情况下,你的内部组件不是包装器的直接子节点。这时可以设置 ngProjectAs 属性:
1
2
3
4
5
6
<app-slot>
<ng-container ngProjectAs="slot">
<div>div</div>
<span>span</span>
</ng-container>
</app-slot>
1
2
3
4
5
6
<app-slot>
<ng-container ngProjectAs="slot">
<div>div</div>
<span>span</span>
</ng-container>
</app-slot>

ng-content 支持一个 select 属性,可以让你在特定的地方投射具体的内容。该属性支持 CSS 选择器(标签选择器、类选择器、属性选择器、…)来匹配你想要的内容。如果 ng-content 上没有设置 select 属性,它将接收全部内容,或接收不匹配任何其他 ng-content 元素的内容。