如果是 external url,走上面的模版,否则走下面 id 为 isLocalUrl 的模版。
external or local,通过正则表达式判断。http/https/mailto 就是 external.
<ng-container *ngTemplateOutlet="content"></ng-container>
在 Angular 开发中,<ng-container *ngTemplateOutlet="content"></ng-container>
是一个非常有用的模式,具备多种实际应用。它通过动态插入模板内容,增强了 Angular 组件的灵活性与动态性。下面会通过详细的解释和示例来剖析这段代码的用途和语法。
基本解释
<ng-container>
是 Angular 提供的虚拟元素,不会被渲染为实际的 DOM 元素。它本质上是一个占位符,可以在其中应用指令和绑定数据,而不影响 DOM 结构。与标准的 <div>
或 <span>
标签不同,它不会生成多余的 HTML 元素,从而有助于保持 DOM 的简洁性。
*ngTemplateOutlet
指令允许我们动态插入 ng-template
的内容。所谓 "ng-template" 是一种 Angular 提供的模板块,可以在需要时被动态创建并插入到视图中。结合 <ng-container>
一起使用,*ngTemplateOutlet
可以引用一个模板,并在该位置插入其内容。
下面是这段代码的具体分解:
<ng-container *ngTemplateOutlet="content"></ng-container>
<ng-container>
:虚拟元素,不会出现在实际的 DOM 中。*ngTemplateOutlet
:结构性指令,用于插入模板。content
:指向要插入的模板,可以是组件中的模板变量。
应用场景
这种模式适用于多种场景,如动态内容展示、多分支逻辑、复用模板等。以下通过实际示例深入说明其具体用途。
简单示例:动态内容展示
假设有一个组件,用于展示用户状态信息,有多个不同的状态。我们希望根据状态动态插入相应的模板内容。
首先定义两个 ng-template
,分别对应不同的用户状态:
<!-- app.component.html -->
<ng-template #activeTemplate>
<p>用户当前处于活跃状态</p>
</ng-template>
<ng-template #inactiveTemplate>
<p>用户当前处于非活跃状态</p>
</ng-template>
<!-- 插入动态内容 -->
<ng-container *ngTemplateOutlet="currentTemplate"></ng-container>
在组件类中定义逻辑,决定哪个模板被插入:
// app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
userStatus: string = 'active'; // 假设状态来自某个服务或逻辑
// 根据状态选择模板
get currentTemplate() {
return this.userStatus === 'active' ? this.activeTemplate : this.inactiveTemplate;
}
// Angular 会自动填充此属性
@ViewChild('activeTemplate', { static: true }) activeTemplate!: TemplateRef<any>;
@ViewChild('inactiveTemplate', { static: true }) inactiveTemplate!: TemplateRef<any>;
}
通过这种方式,我们可以根据 userStatus
动态插入相应的模板,避免了冗长的 ngIf
判断。
复杂示例:表单动态布局
动态表单是另一个常见的应用场景。如果有一个表单,其中部分字段根据用户选择的选项动态变化,可以使用 *ngTemplateOutlet
来实现。
定义多个 ng-template
,每个模板对应一种表单布局:
<!-- app.component.html -->
<form>
<label for="selection">选择布局:</label>
<select id="selection" (change)="onSelectionChange($event.target.value)">
<option value="layout1">布局1</option>
<option value="layout2">布局2</option>
</select>
<ng-container *ngTemplateOutlet="currentLayout"></ng-container>
</form>
<ng-template #layout1>
<label for="field1">字段1:</label>
<input id="field1" type="text">
<br>
<label for="field2">字段2:</label>
<input id="field2" type="text">
</ng-template>
<ng-template #layout2>
<label for="field3">字段3:</label>
<input id="field3" type="text">
<br>
<label for="field4">字段4:</label>
<input id="field4" type="text">
</ng-template>
在组件类中实现切换逻辑:
// app.component.ts
import { Component, ViewChild, TemplateRef } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
@ViewChild('layout1', { static: true }) layout1!: TemplateRef<any>;
@ViewChild('layout2', { static: true }) layout2!: TemplateRef<any>;
currentLayout!: TemplateRef<any>;
constructor() {
this.currentLayout = this.layout1; // 默认布局
}
onSelectionChange(selection: string) {
this.currentLayout = selection === 'layout1' ? this.layout1 : this.layout2;
}
}
这种方式不仅提高了代码的可读性和维护性,还使得界面更加灵活,易于调整。
高级应用:复用组件和模板
在大型应用中,复用组件和模板是非常重要的。通过 *ngTemplateOutlet
,可以实现模板的复用,将常见的 UI 片段封装为 ng-template
,在不同的场景中动态插入。
定义一个共享的 ng-template
:
<!-- shared.templates.html-->
<ng-template #sharedTemplate let-item>
<div class="item-card">
<h3>{{ item.title }}</h3>
<p>{{ item.description }}</p>
</div>
</ng-template>
在组件中复用这个模板:
<!-- item-list.component.html -->
<ng-container *ngFor="let item of items">
<ng-container *ngTemplateOutlet="sharedTemplate; context: { $implicit: item }"></ng-container>
</ng-container>
// item-list.component.ts
import { Component, ViewChild, TemplateRef } from '@angular/core';
@Component({
selector: 'app-item-list',
templateUrl: './item-list.component.html',
styleUrls: ['./item-list.component.css']
})
export class ItemListComponent {
@ViewChild('sharedTemplate', { static: true }) sharedTemplate!: TemplateRef<any>;
items = [
{ title: 'Item 1', description: 'Description 1' },
{ title: 'Item 2', description: 'Description 2' }
];
}
通过上述方法,可以高效地复用模板,避免重复代码,提高开发效率。
总结与优势
通过 *ngTemplateOutlet
和 <ng-container>
的结合使用,可以实现:
- 动态内容展示:根据不同的条件动态插入相应的模板内容,避免了冗长的
ngIf
判断。 - 多样化布局:可根据用户选择动态调整表单或界面布局,增强用户体验。
- 模板复用:将常见的 UI 片段封装为模板,便于在多个组件中复用,提高开发效率和代码一致性。
- 代码简洁:
<ng-container>
本身不会生成实际 DOM 元素,保持了 DOM 的简洁性。
这种灵活的模板插入机制,使得 Angular 组件可以更高效地响应不同的需求与变化,为现代前端开发提供了强有力的支持。通过合理应用,可以显著提升应用程序的灵活性与维护性。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。