Angular - 在模板中调用的模型方法在无限循环中执行
Angular - model method called in template is executed in endless loop
在我的 angular 应用程序中,我定义了模型 class:
import {Type} from "class-transformer"; //https://github.com/typestack/class-transformer
export class Case {
id: string;
@Type(() => Date)
created: string;
status: string;
get customMethod() {
return `Hello ${this.id}`;
}
isPending() {
console.log('isPending() called...');
return this.status == 'new';
}
}
在我的组件中,我从 rest 中获取案例 api:
ngOnInit() {
this.api.getCases().subscribe((cases) => {
this.cases = cases;
});
}
和 getCases() 看起来像:
import {plainToClass} from "class-transformer";
import {Case} from "../models/Case";
// ... come other code
public getCases() {
return this.http.get(`${this.apiUrl}/cases`).pipe(map(response => {
return plainToClass(Case, response as Case[])
}))
}
它工作正常,在我的组件中我得到了 Case 实例。我将这些实例传递给其他子组件:
<app-case-listing [case]="case" *ngFor="let case of cases"></app-case-listing>
那个子组件模板就是:
<li [class.pending]="case.isPending()">
li element for case {{case.customMethod}}, {{case.status}}
</li>
Everythink 几乎可以正常工作 - 除了 isPending() 似乎是在循环中调用的。我不确定这是否是预期的行为(或者它在性能方面是否良好)。当我将控制台日志添加到 "customMethod" getter 时,它也会循环登录。
控制台输出看起来像(成千上万条这样的消息):
isPending() called...
6
breadcrumbs.js:58 isPending() called...
zone.js:2279 [Violation] 'setTimeout' handler took 168ms
6
breadcrumbs.js:58 isPending() called...
6
breadcrumbs.js:58 isPending() called...
zone.js:2279 [Violation] 'setTimeout' handler took 185ms
6
breadcrumbs.js:58 isPending() called...
6
breadcrumbs.js:58 isPending() called...
zone.js:2279 [Violation] 'setTimeout' handler took 186ms
6
breadcrumbs.js:58 isPending() called...
6
breadcrumbs.js:58 isPending() called...
6
breadcrumbs.js:58 isPending() called...
6
breadcrumbs.js:58 isPending() called...
zone.js:2279 [Violation] 'setTimeout' handler took 197ms
所以,我的问题是:
- 这是正确的行为吗?
- 如果没有 - 我如何 fix/optimize 我的代码?
这是正确的行为,您在 ngFor
循环中调用 isPending
方法,该方法会调用每个 Case
实例。您可以将 ChangeDetectionStrategy.OnPush 添加到 app-case-listing
组件以避免不必要的检查。
在我的 angular 应用程序中,我定义了模型 class:
import {Type} from "class-transformer"; //https://github.com/typestack/class-transformer
export class Case {
id: string;
@Type(() => Date)
created: string;
status: string;
get customMethod() {
return `Hello ${this.id}`;
}
isPending() {
console.log('isPending() called...');
return this.status == 'new';
}
}
在我的组件中,我从 rest 中获取案例 api:
ngOnInit() {
this.api.getCases().subscribe((cases) => {
this.cases = cases;
});
}
和 getCases() 看起来像:
import {plainToClass} from "class-transformer";
import {Case} from "../models/Case";
// ... come other code
public getCases() {
return this.http.get(`${this.apiUrl}/cases`).pipe(map(response => {
return plainToClass(Case, response as Case[])
}))
}
它工作正常,在我的组件中我得到了 Case 实例。我将这些实例传递给其他子组件:
<app-case-listing [case]="case" *ngFor="let case of cases"></app-case-listing>
那个子组件模板就是:
<li [class.pending]="case.isPending()">
li element for case {{case.customMethod}}, {{case.status}}
</li>
Everythink 几乎可以正常工作 - 除了 isPending() 似乎是在循环中调用的。我不确定这是否是预期的行为(或者它在性能方面是否良好)。当我将控制台日志添加到 "customMethod" getter 时,它也会循环登录。
控制台输出看起来像(成千上万条这样的消息):
isPending() called...
6
breadcrumbs.js:58 isPending() called...
zone.js:2279 [Violation] 'setTimeout' handler took 168ms
6
breadcrumbs.js:58 isPending() called...
6
breadcrumbs.js:58 isPending() called...
zone.js:2279 [Violation] 'setTimeout' handler took 185ms
6
breadcrumbs.js:58 isPending() called...
6
breadcrumbs.js:58 isPending() called...
zone.js:2279 [Violation] 'setTimeout' handler took 186ms
6
breadcrumbs.js:58 isPending() called...
6
breadcrumbs.js:58 isPending() called...
6
breadcrumbs.js:58 isPending() called...
6
breadcrumbs.js:58 isPending() called...
zone.js:2279 [Violation] 'setTimeout' handler took 197ms
所以,我的问题是:
- 这是正确的行为吗?
- 如果没有 - 我如何 fix/optimize 我的代码?
这是正确的行为,您在 ngFor
循环中调用 isPending
方法,该方法会调用每个 Case
实例。您可以将 ChangeDetectionStrategy.OnPush 添加到 app-case-listing
组件以避免不必要的检查。