通过在模板内使用吸气剂触发角度变化检测循环

问题描述 投票:0回答:2

在模板内使用 getter 似乎会导致 Angular 变化检测进入循环(getter 被调用数百次)。在阅读了大量类似问题后,我似乎无法得到明确的答案。

背景信息:

我确实相信,从可维护性的角度来看,在模板中使用 getter 是最干净的方法,但似乎是因为 Angular 在调用 getter 之前无法知道 getter 值是否发生变化,所以它只是一直调用它。到目前为止我找到了三种替代方案:

  1. 停止使用 getter,将所有属性公开并直接访问它们
  2. 将每个 getter 的值存储到组件上的公共属性中,并绑定它而不是模板中的 getter
  3. 将Angular的changeDetection模式从默认更改为onPush

选项 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 没有找到解决方案(似乎本质上不兼容),如果我找到解决方案,将会更新。

angular typescript loops angular6 angular-changedetection
2个回答
2
投票

使用

ChangeDetectionStrategy.onPush

通过 CLI 创建新组件时,运行以下命令,使其成为项目的默认值。

ng config schematics.@schematics/angular.component.changeDetection OnPush

一般来说,尽量避免复杂的 getter 或从模板内调用函数。如果您需要转换数据,请考虑使用已记忆的Pipes


0
投票

在 Angular 17 中:

import { ChangeDetectionStrategy, Component } from '@angular/core'; 
@Component({
selector: 'app',
standalone: true,
imports: [],
changeDetection: ChangeDetectionStrategy.OnPush,
template: ``
})
© www.soinside.com 2019 - 2024. All rights reserved.