在模板中使用吸气剂触发的角度变化检测循环

时间:2019-03-22 13:55:18

标签: angular typescript loops angular6 angular-changedetection

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

背景信息:

我确实认为,从可维护性的角度来看,在模板内使用getter是最干净的方法,但是似乎是因为Angular在调用它之前不知道getter值是否更改,因此它一直都在调用它。到目前为止,我发现了三种选择:

  1. 停止使用吸气剂,公开所有属性并直接访问它们
  2. 将每个吸气剂的值存储到组件的公共属性中,并将其绑定而不是模板中的吸气剂
  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>

Component.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 output

在Angular中使用复杂模型时,谁能推荐最佳实践以避免不必要的循环?甚至是调试这种行为的正确方法,就目前而言,我是console.logging getter方法并注意内存使用量的峰值。

编辑(答案) 经过更多时间的研究,深入研究堆栈跟踪,我发现无限变化检测循环实际上是由我们注入的称为“哨兵”的服务引起的。当使用console.log触发更改检测时,显然会导致问题。在此处找到了有关此问题的github问题:github.com/getsentry/sentry-javascript/issues/1883找不到解决方案(似乎天生就不兼容),如果找到解决方案,它将进行更新。

1 个答案:

答案 0 :(得分:1)

使用ChangeDetectionStrategy.onPush

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

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

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