Angular使用ngFor迭代时如何避免同一数据获取函数重复调用?
优化方案
- 预计算并缓存每行关联数据(性能最优)
核心逻辑是在获取到表格数据源Details后,提前遍历所有行数据,把每个项目对应的milestones和risks一次性计算好存储到Map或者直接挂载到行数据对象上,模板中直接读取缓存结果,彻底避免函数重复调用。
TS端预处理代码:
// 定义缓存结构存储每个项目的关联数据 projectExtraMap = new Map<string, { milestones: any[], risks: any[] }>(); // 在Details、里程碑/风险源数据更新时调用该方法做预处理 preloadProjectExtra() { this.Details.forEach(item => { const code = item.ProjectCode; this.projectExtraMap.set(code, { milestones: this.getMilestones(code), risks: this.getRisks(code) }); }); }
改造后的模板代码:
<tbody> <tr *ngFor="let item of Details; trackBy: trackByProjectCode"> <div class="row details-row row-cols-lg-2 row-cols-1" *ngIf="closureDetails"> <ng-container *ngIf="projectExtraMap.get(item.ProjectCode) as extra"> <div class="col" [ngClass]="{'d-none': extra.milestones?.length === 0}"> <app-milestone [milestones]="extra.milestones"></app-milestone> </div> <div class="col" [ngClass]="{'d-none': extra.risks?.length === 0}"> <app-risk [risks]="extra.risks"></app-risk> </div> </ng-container> </div> </tr> </tbody>
配套的trackBy优化代码(可选,减少列表重绘开销):
trackByProjectCode(index: number, item: any) { return item.ProjectCode; }
- 使用纯管道(Pure Pipe)缓存调用结果
如果不方便提前预处理数据,可以将查询逻辑封装为Angular纯管道,纯管道只有在输入参数发生变化时才会重新执行,默认不会在每次变更检测时重复调用。配合*ngIf别名存储管道返回结果,即可实现每行仅调用一次查询函数。
管道定义示例:
import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'milestonesByCode', pure: true // 默认为true,可省略 }) export class MilestonesByCodePipe implements PipeTransform { transform(projectCode: string, getMilestones: Function) { return getMilestones(projectCode); } } // 同理实现RisksByCodePipe
改造后的模板代码:
<div class="row details-row row-cols-lg-2 row-cols-1" *ngIf="closureDetails"> <ng-container *ngIf="(item.ProjectCode | milestonesByCode: getMilestones) as milestones"> <div class="col" [ngClass]="{'d-none': milestones?.length === 0}"> <app-milestone [milestones]="milestones"></app-milestone> </div> </ng-container> <ng-container *ngIf="(item.ProjectCode | risksByCode: getRisks) as risks"> <div class="col" [ngClass]="{'d-none': risks?.length === 0}"> <app-risk [risks]="risks"></app-risk> </div> </ng-container> </div>
- 搭配OnPush变更检测策略
给当前表格组件设置ChangeDetectionStrategy.OnPush变更检测策略,只有当组件输入属性变化、内部触发DOM事件、或者手动调用变更检测时才会触发视图更新,可大幅降低变更检测频率,进一步减少不必要的函数调用。
组件配置示例:
import { ChangeDetectionStrategy, Component } from '@angular/core'; @Component({ selector: 'app-your-table', templateUrl: './your-table.component.html', changeDetection: ChangeDetectionStrategy.OnPush }) export class YourTableComponent {}
内容的提问来源于stack exchange,提问作者Sandeep Thomas
相关产品推荐
相关产品推荐

