You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中*ngFor内多次调用getTour函数的优化咨询

优化Angular模板中多次调用getTour的方案

你当前的实现存在两个明显问题:一是每个循环项里多次调用getTour,每次调用都会执行tours.find()遍历数组,当tours数据量大时性能损耗明显;二是Angular的变更检测会频繁触发这些函数调用,导致不必要的重复计算。下面提供几种更优的实现方式:

方案一:提前在组件中处理数据(推荐)

在组件内将reservedTours映射转换为包含Tour对象和预约数量的数组,模板直接遍历处理好的数据,彻底避免在模板中执行查找逻辑。

组件代码:

// 定义处理后的数据结构
processedReservedTours: { tour: Tour; count: number }[] = [];

ngOnInit() {
  // 初始化时处理数据
  this.processReservedTours();
}

// 当tours或reservedTours数据更新时,调用此方法重新处理
processReservedTours() {
  this.processedReservedTours = Object.entries(this.reservedTours).map(([tourId, count]) => ({
    tour: this.tours.find(tour => tour._id === tourId),
    count: count
  }));
}

模板代码:

<tr *ngFor="let item of processedReservedTours" [ngClass]="checkSumCondition() ? 'lower' : 'higher'">
  <td>{{item.tour.name}}</td>
  <td>{{item.tour.country}}</td>
  <td>{{item.tour.price * item.count}} USD</td>
  <td>{{item.tour.startDate}}</td>
  <td>{{item.tour.endDate}}</td>
  <td>{{item.count}}</td>
</tr>

这种方式只在数据变化时执行一次查找逻辑,模板渲染时直接读取属性,性能最优。

方案二:在模板中用*ngIf缓存查找结果

如果不想修改组件逻辑,可以在模板内用*ngIf的语法糖缓存getTour的结果,让每个循环项只调用一次getTour。

模板代码:

<tr *ngFor="let object of reservedTours | keyvalue" [ngClass]="checkSumCondition() ? 'lower' : 'higher'">
  <ng-container *ngIf="getTour(object.key) as tour">
    <td>{{tour.name}}</td>
    <td>{{tour.country}}</td>
    <td>{{tour.price * object.value}} USD</td>
    <td>{{tour.startDate}}</td>
    <td>{{tour.endDate}}</td>
  </ng-container>
  <td>{{object.value}}</td>
</tr>

此方式减少了每个循环项内的函数调用次数,但仍会在Angular变更检测时触发getTour,性能略逊于方案一。

额外优化建议

如果tours数据量较大,建议将tours转换为以_id为键的对象映射,这样查找Tour对象的时间复杂度从O(n)降为O(1):

组件代码:

// 预先将tours转换为id映射
tourMap: { [key: string]: Tour } = {};

ngOnInit() {
  this.tourMap = this.tours.reduce((map, tour) => {
    map[tour._id] = tour;
    return map;
  }, {} as { [key: string]: Tour });
  
  // 再处理reservedTours
  this.processReservedTours();
}

processReservedTours() {
  this.processedReservedTours = Object.entries(this.reservedTours).map(([tourId, count]) => ({
    tour: this.tourMap[tourId],
    count: count
  }));
}

这样无论tours多大,查找单个Tour对象的速度都会非常快。

内容的提问来源于stack exchange,提问作者Cookie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 16:30:59