内置指令 #
一、指令概述 #
Angular指令分为三种类型:
| 类型 | 说明 | 示例 |
|---|---|---|
| 组件 | 带有模板的指令 | @Component |
| 结构指令 | 改变DOM结构 | *ngIf, *ngFor |
| 属性指令 | 改变元素外观或行为 | ngClass, ngStyle |
二、结构指令 #
2.1 *ngIf #
基本用法:
html
<div *ngIf="isVisible">显示内容</div>
<div *ngIf="!isLoading">加载完成</div>
else分支:
html
<div *ngIf="isLoading; else loaded">
加载中...
</div>
<ng-template #loaded>
<div>加载完成</div>
</ng-template>
then-else语法:
html
<div *ngIf="isLoggedIn; then loggedIn; else loggedOut"></div>
<ng-template #loggedIn>
<p>欢迎回来!</p>
</ng-template>
<ng-template #loggedOut>
<p>请先登录</p>
</ng-template>
结合async管道:
html
<div *ngIf="user$ | async as user; else loading">
<p>用户名: {{ user.name }}</p>
</div>
<ng-template #loading>
<p>加载中...</p>
</ng-template>
2.2 *ngFor #
基本用法:
html
<ul>
<li *ngFor="let item of items">
{{ item.name }}
</li>
</ul>
获取索引:
html
<ul>
<li *ngFor="let item of items; let i = index">
{{ i + 1 }}. {{ item.name }}
</li>
</ul>
内置变量:
html
<ul>
<li *ngFor="let item of items;
let i = index;
let first = first;
let last = last;
let even = even;
let odd = odd">
<span *ngIf="first">[首个]</span>
{{ i + 1 }}. {{ item.name }}
<span *ngIf="last">[末尾]</span>
</li>
</ul>
| 变量 | 说明 |
|---|---|
index |
当前项索引(从0开始) |
first |
是否为第一项 |
last |
是否为最后一项 |
even |
索引是否为偶数 |
odd |
索引是否为奇数 |
trackBy优化:
typescript
@Component({
template: `
<li *ngFor="let item of items; trackBy: trackById">
{{ item.name }}
</li>
`
})
export class ExampleComponent {
items = [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' }
];
trackById(index: number, item: Item): number {
return item.id;
}
}
嵌套循环:
html
<div *ngFor="let category of categories">
<h3>{{ category.name }}</h3>
<ul>
<li *ngFor="let product of category.products">
{{ product.name }}
</li>
</ul>
</div>
2.3 *ngSwitch #
基本用法:
html
<div [ngSwitch]="status">
<p *ngSwitchCase="'active'">激活状态</p>
<p *ngSwitchCase="'inactive'">未激活状态</p>
<p *ngSwitchCase="'pending'">待审核</p>
<p *ngSwitchDefault>未知状态</p>
</div>
复杂示例:
typescript
@Component({
template: `
<div [ngSwitch]="user.role">
<app-admin-dashboard *ngSwitchCase="'admin'"></app-admin-dashboard>
<app-user-dashboard *ngSwitchCase="'user'"></app-user-dashboard>
<app-guest-view *ngSwitchDefault></app-guest-view>
</div>
`
})
export class DashboardComponent {
@Input() user: User;
}
三、属性指令 #
3.1 ngClass #
对象语法:
html
<div [ngClass]="{'active': isActive, 'disabled': isDisabled}">
内容
</div>
数组语法:
html
<div [ngClass]="['class1', 'class2', 'class3']">
内容
</div>
字符串语法:
html
<div [ngClass]="'active highlighted'">
内容
</div>
动态类名:
typescript
@Component({
template: `
<div [ngClass]="getClassNames()">内容</div>
`
})
export class ExampleComponent {
isActive = true;
isHighlighted = false;
getClassNames() {
return {
'active': this.isActive,
'highlighted': this.isHighlighted,
'text-bold': true
};
}
}
结合条件:
html
<div [ngClass]="{
'status-active': status === 'active',
'status-inactive': status === 'inactive',
'status-pending': status === 'pending'
}">
{{ status }}
</div>
3.2 ngStyle #
对象语法:
html
<div [ngStyle]="{'color': 'red', 'font-size': '16px'}">
内容
</div>
动态样式:
html
<div [ngStyle]="{
'color': isActive ? 'green' : 'gray',
'font-size': fontSize + 'px',
'background-color': bgColor
}">
动态样式内容
</div>
使用组件属性:
typescript
@Component({
template: `
<div [ngStyle]="divStyles">内容</div>
`
})
export class ExampleComponent {
divStyles = {
'color': 'white',
'background-color': 'blue',
'padding': '20px',
'border-radius': '8px'
};
}
条件样式:
html
<div [ngStyle]="{
'background-color': isLoading ? '#f0f0f0' : '#ffffff',
'opacity': isLoading ? 0.5 : 1
}">
<p *ngIf="!isLoading">内容加载完成</p>
<p *ngIf="isLoading">加载中...</p>
</div>
四、Angular 17+ 新控制流语法 #
4.1 @if语法 #
html
@if (isVisible) {
<div>显示内容</div>
}
@if (isLoading) {
<div>加载中...</div>
} @else {
<div>加载完成</div>
}
@if (score >= 90) {
<p>优秀</p>
} @else if (score >= 60) {
<p>及格</p>
} @else {
<p>不及格</p>
}
4.2 @for语法 #
html
@for (item of items; track item.id) {
<li>{{ item.name }}</li>
}
@for (item of items; track item.id; let i = $index, let first = $first) {
<li [class.first]="first">
{{ i + 1 }}. {{ item.name }}
</li>
} @empty {
<li>暂无数据</li>
}
内置变量:
| 变量 | 说明 |
|---|---|
$index |
当前索引 |
$first |
是否为第一项 |
$last |
是否为最后一项 |
$even |
索引是否为偶数 |
$odd |
索引是否为奇数 |
$count |
总数量 |
4.3 @switch语法 #
html
@switch (status) {
@case ('active') {
<p>激活状态</p>
}
@case ('inactive') {
<p>未激活状态</p>
}
@default {
<p>未知状态</p>
}
}
五、指令对比 #
5.1 *ngIf vs [hidden] #
html
<!-- *ngIf: 完全移除DOM -->
<div *ngIf="isVisible">内容</div>
<!-- [hidden]: 隐藏DOM,但保留在DOM中 -->
<div [hidden]="!isVisible">内容</div>
| 方式 | 特点 | 适用场景 |
|---|---|---|
*ngIf |
移除DOM | 不频繁切换 |
[hidden] |
隐藏DOM | 频繁切换 |
5.2 ngClass vs class绑定 #
html
<!-- 单个类 -->
<div [class.active]="isActive">内容</div>
<!-- 多个类 -->
<div [ngClass]="{'active': isActive, 'disabled': isDisabled}">内容</div>
5.3 ngStyle vs style绑定 #
html
<!-- 单个样式 -->
<div [style.color]="'red'">内容</div>
<!-- 多个样式 -->
<div [ngStyle]="{'color': 'red', 'font-size': '16px'}">内容</div>
六、实际应用示例 #
6.1 条件渲染列表 #
typescript
@Component({
template: `
<div class="user-list">
<div *ngIf="users.length > 0; else empty">
<div *ngFor="let user of users; let i = index"
[ngClass]="{'even': i % 2 === 0, 'odd': i % 2 === 1}">
<span [ngStyle]="{'color': user.active ? 'green' : 'gray'}">
{{ user.name }}
</span>
<span *ngIf="user.isAdmin" class="badge">管理员</span>
</div>
</div>
<ng-template #empty>
<p class="empty-message">暂无用户数据</p>
</ng-template>
</div>
`
})
export class UserListComponent {
users: User[] = [];
}
6.2 状态显示 #
typescript
@Component({
template: `
<div [ngSwitch]="order.status" class="status-badge">
<span *ngSwitchCase="'pending'" class="badge-warning">待处理</span>
<span *ngSwitchCase="'processing'" class="badge-info">处理中</span>
<span *ngSwitchCase="'shipped'" class="badge-primary">已发货</span>
<span *ngSwitchCase="'delivered'" class="badge-success">已送达</span>
<span *ngSwitchCase="'cancelled'" class="badge-danger">已取消</span>
<span *ngSwitchDefault class="badge-secondary">未知状态</span>
</div>
`
})
export class OrderStatusComponent {
@Input() order: Order;
}
6.3 表格渲染 #
typescript
@Component({
template: `
<table class="table">
<thead>
<tr>
<th>#</th>
<th>名称</th>
<th>价格</th>
<th>状态</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let product of products; let i = index"
[ngClass]="{
'row-even': i % 2 === 0,
'row-odd': i % 2 === 1,
'row-highlight': product.featured
}">
<td>{{ i + 1 }}</td>
<td>{{ product.name }}</td>
<td [ngStyle]="{'color': product.discount ? 'red' : 'inherit'}">
{{ product.price | currency }}
</td>
<td>
<span [ngSwitch]="product.status">
<span *ngSwitchCase="'in_stock'">有货</span>
<span *ngSwitchCase="'out_of_stock'">缺货</span>
<span *ngSwitchDefault>未知</span>
</span>
</td>
</tr>
</tbody>
</table>
`
})
export class ProductTableComponent {
products: Product[] = [];
}
七、性能优化建议 #
7.1 使用trackBy #
typescript
@Component({
template: `
<li *ngFor="let item of items; trackBy: trackById">
{{ item.name }}
</li>
`
})
export class ExampleComponent {
trackById(index: number, item: Item): number {
return item.id;
}
}
7.2 避免频繁DOM操作 #
html
<!-- 推荐:使用hidden -->
<div [hidden]="!isVisible">内容</div>
<!-- 不推荐:频繁使用ngIf -->
<div *ngIf="isVisible">内容</div>
7.3 使用OnPush策略 #
typescript
@Component({
selector: 'app-list',
template: `...`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ListComponent {
@Input() items: Item[];
}
八、总结 #
| 指令 | 类型 | 用途 |
|---|---|---|
*ngIf |
结构 | 条件渲染 |
*ngFor |
结构 | 列表渲染 |
*ngSwitch |
结构 | 多条件分支 |
ngClass |
属性 | 动态类名 |
ngStyle |
属性 | 动态样式 |
下一步:自定义指令
最后更新:2026-03-26