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
相关产品推荐
相关产品推荐

