- Angular 教程
- Angular - 首页
- Angular - 概述
- Angular - 特性
- Angular - 优势与劣势
- Angular 基础
- Angular - 环境搭建
- Angular - 第一个应用
- Angular - MVC 架构
- Angular 组件
- Angular - 组件
- Angular - 组件生命周期
- Angular - 视图封装
- Angular - 组件交互
- Angular - 组件样式
- Angular - 嵌套组件
- Angular - 内容投影
- Angular - 动态组件
- Angular - 元素
- Angular 模板
- Angular - 模板
- Angular - 文本插值
- Angular - 模板语句
- Angular - 模板中的变量
- Angular - SVG 作为模板
- Angular 数据绑定
- Angular - 数据绑定及其类型
- Angular - 数据绑定
- Angular - 事件绑定
- Angular - 属性绑定
- Angular - 属性绑定
- Angular - 类和样式绑定
- Angular 指令
- Angular - 指令
- Angular - 内置指令
- Angular 管道
- Angular - 管道
- Angular - 使用管道转换数据
- Angular 依赖注入
- Angular - 依赖注入
- Angular HTTP 客户端编程
- Angular - 服务
- Angular - HTTP 客户端
- Angular - 请求
- Angular - 响应
- Angular - GET 请求
- Angular - PUT 请求
- Angular - DELETE 请求
- Angular - JSON-P
- Angular - 使用 HTTP 进行 CRUD 操作
- Angular 路由
- Angular - 路由
- Angular - 导航
- Angular - Angular Material
- Angular 动画
- Angular - 动画
- Angular 表单
- Angular - 表单
- Angular - 表单验证
- Angular Service Workers 和 PWA
- Angular - Service Workers 和 PWA
- Angular 测试
- Angular - 测试概述
- Angular NgModules
- Angular - 模块介绍
- Angular 高级
- Angular - 身份验证和授权
- Angular - 国际化
- Angular - 可访问性
- Angular - Web Workers
- Angular - 服务器端渲染
- Angular - Ivy 编译器
- Angular - 使用 Bazel 构建
- Angular - 向后兼容性
- Angular - 响应式编程
- Angular - 指令和组件之间的数据共享
- Angular 工具
- Angular - CLI
- Angular 其他
- Angular - 第三方控件
- Angular - 配置
- Angular - 数据显示
- Angular - 装饰器和元数据
- Angular - 基本示例
- Angular - 错误处理
- Angular - 测试和项目构建
- Angular - 生命周期钩子
- Angular - 用户输入
- Angular - 新特性?
- Angular 有用资源
- Angular - 快速指南
- Angular - 有用资源
- Angular - 讨论
Angular - 内容投影
内容投影是 Angular 组件中的一种技术,它允许将外部内容(来自组件的使用者)与布局和样式一起包含在组件模板的特定区域中。一个简单的例子如下:
让我们考虑一个组件,content-projection-sample 具有以下模板:
<p>This is content from the component template</p> <ng-content></ng-content> <p>This is another content from component template</p>
可以使用以下方法来包含外部数据:
<content-projection-sample> <p>This is content external content</p> </content-projection-sample>
组件的输出将如下所示:
<p>This is content from the component template</p> <p>This is content external content</p> <p>This is another content from component template</p>
在这里,外部内容放置/投影在 ng-content 的位置。
让我们通过创建上面解释的组件来理解内容投影。
步骤 1:创建一个新的组件,content-projection-sample
$ ng generate component content-projection-sample CREATE src/app/content-projection-sample/content-projection-sample.component.css (0 bytes) CREATE src/app/content-projection-sample/content-projection-sample.component.html (40 bytes) CREATE src/app/content-projection-sample/content-projection-sample.component.spec.ts (680 bytes) CREATE src/app/content-projection-sample/content-projection-sample.component.ts (276 bytes) UPDATE src/app/app.module.ts (701 bytes)
步骤 2:在模板 content-projection-sample.component.html 中添加 ng-content 标签,如下所示:
<p>This is content from the component template</p> <ng-content></ng-content> <p>This is another content from component template</p>
步骤 3:在 app 组件的 app.component.html 中使用 content-projection-sample 组件,如下所示:
<app-content-projection-sample> <p>This is external content</p> </app-content-projection-sample> <router-outlet></router-outlet>
步骤 4:运行应用程序并检查输出。
<app-content-projection-sample _ngcontent-ng-c2678441144="" _nghost-ng-c981906799=""> <p _ngcontent-ng-c981906799=""> This is content from the component template</p> <p _ngcontent-ng-c2678441144=""> This is external content</p> <p _ngcontent-ng-c981906799=""> This is another content from component template</p> </app-content-projection-sample>
步骤 5:应用程序的输出如下所示:
多插槽内容投影
只包含一个内容投影的组件称为单插槽内容投影。Angular 也允许将多个内容投影到组件中,这称为多插槽内容投影。让我们看看如何通过修改上面的示例来使用多个内容投影。
在组件模板 content-projection-sample.component.html 中添加另一个带有选择器属性的 ng-content,如下所示:
<p>This is content from the component template</p> <ng-content></ng-content> <p>This is another content from component template</p> <ng-content select="[second]"></ng-content>
更新 app 组件模板 app.component.html,如下所示:
<app-content-projection-sample> <p>This is external content</p> <p second>This is yet another external content</p> </app-content-projection-sample> <router-outlet></router-outlet>
这里,组件模板中设置的选择器属性(第二个)的值用于要投影的内容。
现在,运行应用程序并检查输出。
<app-content-projection-sample _ngcontent-ng-c2332747330="" _nghost-ng-c2742507360=""> <p _ngcontent-ng-c2742507360=""> This is content from the component template</p> <p _ngcontent-ng-c2332747330=""> This is external content</p> <p _ngcontent-ng-c2742507360=""> This is another content from component template</p> <p _ngcontent-ng-c2332747330="" second=""> This is yet another external content</p> </app-content-projection-sample>
应用程序的输出如下所示:
ngProjectAs
ngProjectAs 是一个特殊的属性,用于在复杂场景中投影内容。一个例子是使用 ng-container 来布局模板。众所周知,ng-container 本身不渲染,而是渲染其子内容,我们需要使用 ngProjectAs 属性来投影其内容。
让我们更改上面的示例以使用 ng-container 和 ngProjectAs 属性。
更新 app 组件模板,**app.component.html**,如下所示:
<app-content-projection-sample> <p>This is external content</p> <ng-container ngProjectAs="second"> <p>This is yet another external content</p> </ng-container> </app-content-projection-sample> <router-outlet></router-outlet>
这里,组件模板中设置的选择器属性(第二个)的值用于 ng-container。
现在,运行应用程序并检查输出。
<app-content-projection-sample _ngcontent-ng-c2332747330="" _nghost-ng-c2742507360=""> <p _ngcontent-ng-c2742507360=""> This is content from the component template</p> <p _ngcontent-ng-c2332747330=""> This is external content</p> <p _ngcontent-ng-c2742507360=""> This is another content from component template</p> <p _ngcontent-ng-c2332747330="" second=""> This is yet another external content</p> </app-content-projection-sample>
应用程序的输出如下所示:
条件内容投影
条件内容投影是在满足特定条件时投影内容。我们可以使用 ng-content 来有条件地投影内容。但是不推荐这样做,因为即使内容不会被渲染,ng-content 也会被初始化。相反,我们可以使用 ng-template 来安全地投影内容,因为它只会在内容将被渲染时才初始化内容。
使用 ng-template 投影内容的总体思路如下:
步骤 1:创建一个指令(例如 TestDirective)来定位和选择 ng-template,它将用于存储/包含要投影的内容。该指令将在构造函数中初始化期间获取 ng-template 的引用。此模板引用将由父组件用来获取内容并在适当的位置渲染它。
constructor(public tmpl_ref: TemplateRef<unknown>) { }
步骤 2:使用 @ContentChild 装饰器在父组件(提供内容投影的组件)中获取指令实例,如下所示:
@ContentChild(TestDirective) testDirectiveInstance!: TestDirective;
步骤 3:在父组件的模板中使用 ngTemplateOutlet、ngIf 和 ng-container 投影内容,如下所示:
<div *ngIf="condition"> <ng-container [ngTemplateOutlet]="testDirectiveInstance.tmpl_ref"></ng-container> </div>
这里:
condition 是用于通过 *ngIf 切换内容投影的实际条件。
ngTemplateOutlet 是用于注入和渲染给定模板的内置指令。
testDirectiveInstance.tmpl_ref 是对实际模板的引用,该模板包含要投影的操作内容。该模板将使用 ng-template 放置在使用者组件的模板中。我们将在下一步中看到。
ng-container 用于确保在内容不会被投影时不会生成不需要的内容/标签。
步骤 4:最后,通过在具有步骤 1 中创建的指令的模板中设置要投影的内容,在任何想要的地方使用该组件。
<ng-template appTestDirective> Hi, I am coming from conditional template </ng-template>
让我们通过更新我们的内容投影示例并更详细地了解条件投影来创建一个可工作的演示。
步骤 1:使用 angular CLI 创建一个指令 greet-content,如下所示:
ng generate directive greet-content CREATE src/app/greet-content.directive.spec.ts (249 bytes) CREATE src/app/greet-content.directive.ts (153 bytes) UPDATE src/app/app.module.ts (795 bytes)
步骤 2:更新指令并获取模板引用,如下所示:
import { Directive, TemplateRef } from '@angular/core'; @Directive({ selector: '[appGreetContent]' }) export class GreetContentDirective { constructor(public template: TemplateRef<unknown>) { } }
这里:
selector 是识别指令的关键。
template 是通过构造函数注入(依赖注入概念)注入到指令中的 TemplateRef 类型引用对象。
步骤 3:更新组件 ContentProjectionSampleComponent 以获取指令对象并设置实际条件,如下所示:
import { Component, ContentChild } from '@angular/core'; import { GreetContentDirective } from '../greet-content.directive'; @Component({ selector: 'app-content-projection-sample', templateUrl: './content-projection-sample.component.html', styleUrls: ['./content-projection-sample.component.css'] }) export class ContentProjectionSampleComponent { show = true; @ContentChild(GreetContentDirective) greet!: GreetContentDirective; }
这里:
show 是一个变量,它保存决定性条件。
@ContentChild 是一个装饰器,它将用于获取指令实例。
步骤 4:在组件的模板中,使用 ngIf 检查条件,使用 ng-container 和 ngTemplateOutlet 在组件的模板中显示模板 (greet.template),如下所示:
<p>This is content from the component template</p> <ng-content></ng-content> <p>This is another content from component template</p> <ng-content select="[second]"></ng-content> <div *ngIf="show"> <ng-container [ngTemplateOutlet]="greet.template"></ng-container> </div>
步骤 5:最后,使用该组件及其在 app 组件中的条件投影,如下所示:
<app-content-projection-sample> <p>This is external content</p> <ng-container ngProjectAs="second"> <p>This is yet another external content</p> </ng-container> <ng-template appGreetContent> Hi, I am coming from conditional template </ng-template> </app-content-projection-sample> <router-outlet></router-outlet>
步骤 6:运行应用程序并检查输出,以发现内容是通过条件投影概念渲染的。
步骤 7:将组件中的条件 show 更新为 false 并检查输出,以发现 ng-template 内容未渲染。
export class ContentProjectionSampleComponent { show = false; @ContentChild(GreetContentDirective) greet!: GreetContentDirective; }