南充市网站建设_网站建设公司_改版升级_seo优化
2026/1/2 9:55:44 网站建设 项目流程

Angular 作为前端主流的企业级框架,指令(Directive)是其核心特性之一,而结构型指令更是日常开发中高频使用的工具 —— 它们直接塑造 DOM 结构,决定元素的 “生死” 与 “循环”。其中*ngIf*ngFor作为最基础也最核心的内置结构指令,掌握其使用技巧能大幅提升开发效率,避免常见坑点。本文将从基础用法到进阶技巧,带你吃透这两个指令。

一、先搞懂:什么是结构型指令?

结构型指令的核心作用是修改 DOM 结构,比如添加、删除、替换元素,或重复渲染一组元素。Angular 内置的结构指令都以*开头(语法糖),本质是对<ng-template>的简化封装。

需要注意:一个元素上不能同时使用多个结构型指令(比如不能同时写*ngIf*ngFor),这是 Angular 的核心规则,避免指令执行顺序冲突。

二、*ngIf:条件渲染的正确姿势

*ngIf用于根据条件决定是否渲染元素(而非隐藏),这是它与[hidden]的核心区别 ——*ngIf不满足条件时,元素会从 DOM 中完全移除,而[hidden]只是通过 CSS 隐藏,仍存在于 DOM 中。

1. 基础用法:简单条件判断

最常用的场景是根据布尔值渲染元素:

<!-- 基础写法 --> <div *ngIf="isShow">满足条件,我会显示</div> <!-- 反向条件 --> <div *ngIf="!isUserLogin">未登录,请先登录</div>

对应的组件类:

@Component({ selector: 'app-ngIf-demo', templateUrl: './ngIf-demo.component.html' }) export class NgIfDemoComponent { isShow = true; isUserLogin = false; }

2. 进阶:else 分支与<ng-template>

当需要 “满足条件显示 A,不满足显示 B” 时,可结合else<ng-template>实现:

<!-- 带else的写法 --> <div *ngIf="hasPermission; else noPermission"> 您有访问权限,可操作 </div> <!-- ng-template定义else模板 --> <ng-template #noPermission> <div>无访问权限,请联系管理员</div> </ng-template>

这里#noPermission是模板引用变量,else后直接引用即可。

3. 高级:then-else 多分支

如果需要 “满足条件显示 A,否则显示 B,且可动态切换”,可使用then语法:

<div *ngIf="status; then successTpl else errorTpl"></div> <ng-template #successTpl> <div>操作成功 ✅</div> </ng-template> <ng-template #errorTpl> <div>操作失败 ❌</div> </ng-template>

这种写法更灵活,适合多状态切换的场景。

4. 避坑:*ngIf 与 null/undefined 的处理

*ngIf会将0''nullundefinedfalse都判定为 “假”,但实际开发中需注意:

<!-- 错误示例:若list为[],仍会显示(因为[]是真) --> <div *ngIf="list">列表有数据</div> <!-- 正确示例:判断数组是否有内容 --> <div *ngIf="list && list.length > 0">列表有数据</div>

5. 小技巧:利用 * ngIf 提升性能

对于复杂组件(比如包含大量逻辑的表单、图表),用*ngIf替代[hidden],可避免组件初始化和变更检测,提升页面性能:

<!-- 差:组件仍会初始化,只是隐藏 --> <app-complex-chart [hidden]="!showChart"></app-complex-chart> <!-- 优:不满足条件时,组件完全不渲染 --> <app-complex-chart *ngIf="showChart"></app-complex-chart>

三、*ngFor:循环渲染的核心技巧

*ngFor用于遍历数组 / 可迭代对象,重复渲染元素,是列表渲染的核心指令。掌握其进阶用法,能解决大部分循环场景的问题。

1. 基础用法:遍历数组

<!-- 基础遍历 --> <ul> <li *ngFor="let item of userList"> {{ item.name }} - {{ item.age }}岁 </li> </ul>

组件类:

export class NgForDemoComponent { userList = [ { name: '张三', age: 25 }, { name: '李四', age: 30 }, { name: '王五', age: 28 } ]; }

2. 必加项:trackBy 提升性能

默认情况下,*ngFor会通过对象引用判断元素是否变化,当数组重新赋值(比如接口刷新)时,即使数据内容不变,Angular 也会销毁并重建所有 DOM 元素,性能极低。

解决方案:使用trackBy指定唯一标识

<!-- 带trackBy的遍历 --> <ul> <li *ngFor="let item of userList; trackBy: trackByUserId"> {{ item.name }} - {{ item.age }}岁 </li> </ul>

组件类中定义trackBy方法:

// 以id为唯一标识 trackByUserId(index: number, item: any): number { return item.id; // 确保item有唯一的id字段 }

trackBy接收两个参数:index(索引)和item(当前项),返回值必须是唯一的(如 id、手机号等)。

3. 常用变量:index、even、odd、first、last

*ngFor提供了内置变量,满足特殊场景的需求:

变量名含义
index当前项的索引(从 0 开始)
even是否为偶数项(布尔值)
odd是否为奇数项(布尔值)
first是否为第一项(布尔值)
last是否为最后一项(布尔值)

示例:

<table> <tr *ngFor="let item of userList; trackBy: trackByUserId; let i = index; let isEven = even; let isFirst = first; let isLast = last" [style.backgroundColor]="isEven ? '#f5f5f5' : '#fff'" > <td>{{ i + 1 }}</td> <!-- 索引从1开始 --> <td>{{ item.name }}</td> <td>{{ isFirst ? '✅ 第一项' : isLast ? '🔚 最后一项' : '' }}</td> </tr> </table>

4. 嵌套 * ngFor:多维数组遍历

处理二维数组(比如表格的行和列)时,可嵌套*ngFor

<!-- 嵌套循环:遍历行和列 --> <table border="1"> <tr *ngFor="let row of tableData; trackBy: trackByRowIndex"> <td *ngFor="let cell of row; trackBy: trackByCellIndex"> {{ cell }} </td> </tr> </table>

组件类:

tableData = [ ['姓名', '年龄', '性别'], ['张三', 25, '男'], ['李四', 30, '女'] ]; trackByRowIndex(index: number): number { return index; } trackByCellIndex(index: number): number { return index; }

5. 避坑:ngFor 与ngIf 的冲突解决

前面提到 “一个元素不能同时用多个结构指令”,如果需要 “循环且条件过滤”,有两种解决方案:

方案 1:外层套<ng-container>(推荐)

<ng-container>是 Angular 的 “空容器”,不会生成实际 DOM,专门用于包裹指令:

<ul> <ng-container *ngFor="let item of userList; trackBy: trackByUserId"> <!-- 只显示年龄大于25的用户 --> <li *ngIf="item.age > 25"> {{ item.name }} - {{ item.age }}岁 </li> </ng-container> </ul>
方案 2:提前过滤数组(性能更优)

在组件类中先过滤数据,模板中直接遍历过滤后的数组:

// 组件类 get filteredUserList() { return this.userList.filter(item => item.age > 25); }
<!-- 模板 --> <ul> <li *ngFor="let item of filteredUserList; trackBy: trackByUserId"> {{ item.name }} - {{ item.age }}岁 </li> </ul>

这种方式减少了模板中的逻辑,且避免了循环内的条件判断,性能更好。

四、总结:核心要点

  1. *ngIf是 “DOM 级别的条件渲染”,而非隐藏,适合控制元素的存在与否,优先于[hidden]
  2. *ngIfelse/then分支需结合<ng-template>使用,满足多状态切换;
  3. *ngFor必须加trackBy,避免数组更新时 DOM 全量重建,提升性能;
  4. 利用*ngFor的内置变量(index/even/odd 等)解决特殊场景;
  5. 避免在同一元素上混用*ngIf*ngFor,优先用<ng-container>或提前过滤数组。

掌握这两个指令的核心技巧,能解决 Angular 开发中 80% 的 DOM 结构控制场景。后续还可以探索自定义结构指令,进一步扩展 Angular 的 DOM 操作能力。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询