Skip to main content

内容投影

内容投影就是将 angular 组件包裹的 html 插入到组件模版的某个位置

单插槽的内容投影

组件从单一来源接收内容

import { Component } from "@angular/core";

@Component({
selector: "app-zippy-basic",
template: `
<h2>Single-slot content projection</h2>
<ng-content></ng-content>
`
})
export class ZippyBasicComponent {}
<app-zippy-basic>
<p>Is content projection cool?</p>
</app-zippy-basic>

<ng-content> 元素是一个占位符,它不会创建真正的 DOM 元素。<ng-content> 的那些自定义属性将被忽略。

多插槽的内容投影

组件从多个来源接收内容

一个组件可以具有多个插槽。每个插槽可以指定一个 CSS 选择器,该选择器会决定将哪些内容放入该插槽。可以给 ng-content 组件上添加 select 属性来实现这个功能 select 属性的值是一个 css 选择器

import { Component } from "@angular/core";

@Component({
selector: "app-zippy-multislot",
template: `
<h2>Multi-slot content projection</h2>

Default:
<ng-content></ng-content>

Question:
<ng-content select="[question]"></ng-content>
`
})
export class ZippyMultislotComponent {}

使用 question 属性的内容将投影到带有 select=[question] 属性的 <ng-content> 元素。

<app-zippy-multislot>
<p question>
Is content projection cool?
</p>
<p>Let's learn about content projection!</p>
</app-zippy-multislot>
不带 SELECT 属性的 NG-CONTENT

如果你的组件包含不带 select 属性的 <ng-content> 元素,则该实例将接收所有与其他 <ng-content> 元素都不匹配的投影组件。

在前面的示例中,只有第二个 <ng-content> 元素定义了 select 属性。结果,第一个 <ng-content> 就会元素接收投影到组件中的任何其他内容。

有条件的内容投影

有条件的内容投影

使用 ng-template 来实现

在这种情况下,不建议使用 ng-content 元素,因为只要组件的使用者提供了内容,即使该组件从未定义 ng-content 元素或该 ng-content 元素位于 *ngIf 语句的内部,该内容也总会被初始化。

ngProjectAs

在某些情况下,你可能希望将内容投影为其他元素。例如,你要投影的内容可能是另一个元素的子元素。可以用 ngProjectAs(值也是一个 CSS 选择器) 属性来完成此操作。

<ng-container ngProjectAs="[question]">
<p>Is content projection cool?</p>
</ng-container>

这个 ng-container 元素中的内容也会被投影到组件的 ng-content && select='[question]' 中