在模板内使用 getter 似乎会导致 Angular 变化检测进入循环(getter 被调用数百次)。在阅读了大量类似问题后,我似乎无法得到明确的答案。
背景信息:
我确实相信,从可维护性的角度来看,在模板中使用 getter 是最干净的方法,但似乎是因为 Angular 在调用 getter 之前无法知道 getter 值是否发生变化,所以它只是一直调用它。到目前为止我找到了三种替代方案:
选项 1 似乎与使用 Typescript 类的好处违反直觉。选项 2 看起来像是不必要的代码重复并降低可维护性,选项 3 则需要大量重构。
这是一个示例(出于说明目的而简化)
型号:
export class UserModel {
private id: string;
get getId() {
console.log('Getting id');
return this.id;
}
set setId(id) {
this.id = id;
}
constructor() {
}
}
Component.html
<h1>Test</h1>
<p>{{user.getId}}</p>
组件.ts
import {Component, OnInit} from '@angular/core';
import {TestModel} from './test.model';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
public user: UserModel;
ngOnDestroy() {
if (this.userObserver) { this.userObserver.unsubscribe(); }
}
ngOnInit() {
this.userObserver = this.userObservable.subscribe(
(data: UserModel) => {
this.user = data;
},
(err: any) => {
console.error(err);
});
}
}
会输出以下控制台日志: console.log输出
任何人都可以推荐最佳实践,以避免在 Angular 中处理复杂模型时出现不必要的循环吗?或者甚至是调试此类行为的正确方法,就目前而言,我正在控制台。记录 getter 方法并观察内存使用峰值。
编辑(答案) 经过更多时间的调查,挖掘堆栈跟踪,我发现无限变化检测循环实际上是由我们注入的名为“Sentry”的服务引起的。显然,当使用 console.log 触发更改检测时,它会导致问题。在这里发现了一个关于它的 github 问题:github.com/getsentry/sentry-javascript/issues/1883 没有找到解决方案(似乎本质上不兼容),如果我找到解决方案,将会更新。
使用
ChangeDetectionStrategy.onPush
通过 CLI 创建新组件时,运行以下命令,使其成为项目的默认值。
ng config schematics.@schematics/angular.component.changeDetection OnPush
一般来说,尽量避免复杂的 getter 或从模板内调用函数。如果您需要转换数据,请考虑使用已记忆的Pipes。
在 Angular 17 中:
import { ChangeDetectionStrategy, Component } from '@angular/core';
@Component({
selector: 'app',
standalone: true,
imports: [],
changeDetection: ChangeDetectionStrategy.OnPush,
template: ``
})