Angular模板ul列表中如何避免使用函数?
如何在Angular模板中避免使用函数?
Angular模板里调用函数会带来性能问题:变更检测周期会频繁触发这些函数,哪怕数据没有变化,尤其是在*ngFor循环中,每一次检测都会给列表中的每一项调用一遍函数,产生大量无用计算。以下是几种可行的解决方法:
方法1:提前预处理数据
在组件内部把原始数据转换成视图需要的格式,直接在模板中使用处理好的字段即可。可以给每个数据项补充视图所需的状态文本和类名,或者单独维护一个处理后的数组。
修改post.component.ts:
import { Details, Status } from 'models'; import { SimpleChanges, OnInit, OnChanges } from '@angular/core'; export class PostComponent implements OnInit, OnChanges { @Input() pckgs: Details[]; processedPackages: Array<{item: Details, displayStatus: string, statusClass: string}>; ngOnInit() { this.processPackages(); } // 监听输入数据变化,更新时重新处理 ngOnChanges(changes: SimpleChanges) { if (changes['pckgs']) { this.processPackages(); } } private processPackages() { this.processedPackages = this.pckgs.map(pckg => { let displayStatus = ''; let statusClass = ''; // 这里替换成原myFunc1的逻辑 switch(pckg.status) { case Status.P: displayStatus = 'processing'; statusClass = 'processing-class'; // 替换成myFunc1返回的实际类名 break; case Status.D: displayStatus = 'finished'; statusClass = 'finished-class'; // 替换成myFunc1返回的实际类名 break; default: displayStatus = ''; statusClass = ''; } return { item: pckg, displayStatus, statusClass }; }); } }
修改post.component.html:
<ul> <li *ngFor="let pkg of processedPackages; trackBy: trackId"> <span [ngClass]="pkg.statusClass">{{pkg.displayStatus}}</span> </li> </ul>
方法2:使用纯管道封装逻辑
如果状态转换逻辑需要在多个组件复用,可以把逻辑封装成纯管道。纯管道只会在输入值发生变化时重新计算,不会每次变更检测都触发。
先创建状态文本转换管道:
import { Pipe, PipeTransform } from '@angular/core'; import { Details, Status } from 'models'; @Pipe({ name: 'statusDisplay' }) export class StatusDisplayPipe implements PipeTransform { transform(pckg: Details): string { return pckg.status === Status.P ? 'processing' : pckg.status === Status.D ? 'finished' : ''; } }
再创建类名转换管道(对应原myFunc1):
import { Pipe, PipeTransform } from '@angular/core'; import { Details, Status } from 'models'; @Pipe({ name: 'statusClass' }) export class StatusClassPipe implements PipeTransform { transform(pckg: Details): string { // 这里实现原myFunc1的逻辑,示例如下: return pckg.status === Status.P ? 'processing-cls' : pckg.status === Status.D ? 'finished-cls' : ''; } }
记得把这两个管道添加到所在模块的declarations数组中,之后就可以在模板里使用:
<ul> <li *ngFor="let pckg of pckgs; trackBy: trackId"> <span [ngClass]="pckg | statusClass">{{pckg | statusDisplay}}</span> </li> </ul>
方法3:模板内直接写条件表达式(适合简单逻辑)
如果逻辑足够简单,也可以直接在模板中写三元表达式,省去函数调用。但逻辑复杂时会导致模板可读性变差,只推荐用于简单场景:
<ul> <li *ngFor="let pckg of pckgs; trackBy: trackId"> <span [ngClass]="pckg.status === Status.P ? 'processing-cls' : pckg.status === Status.D ? 'finished-cls' : ''" > {{pckg.status === Status.P ? 'processing' : pckg.status === Status.D ? 'finished' : ''}} </span> </li> </ul>
注意:如果要在模板中直接使用Status枚举,需要在组件中添加Status = Status;,把枚举暴露给模板。
内容的提问来源于stack exchange,提问作者Haradzieniec
相关产品推荐
相关产品推荐

