Angular - метод модели, вызываемый в шаблоне, выполняется в бесконечном цикле - PullRequest
0 голосов
/ 17 мая 2019

В моем угловом приложении определен класс модели:

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';
  }

}

В моем компоненте я выбираю чехлы из остальных 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», он также входит в цикл.

Вывод на консоль выглядит (тысячи таких сообщений):

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

Итак, мои вопросы:

  1. Это правильное поведение?
  2. Если нет - как я могу исправить / оптимизировать мой код?

1 Ответ

1 голос
/ 17 мая 2019

Это правильное поведение, вы вызываете метод isPending внутри цикла ngFor, и метод вызывает для каждого экземпляра Case.Вы можете добавить ChangeDetectionStrategy.OnPush к app-case-listing компоненту во избежание ненужных проверок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...