Является ли нормальным для Angular повторный рендеринг бесконечно, даже если не было внесено никаких изменений? - PullRequest
0 голосов
/ 25 июня 2018

Вопрос

Предназначен ли Angular для постоянной повторной проверки всего, чтобы обнаружить изменения?Я из мира React, и я ожидал чего-то вроде event triggered -> re-rendering.Я не знаю, если это что-то из моего приложения или что-то из Angular.

Если у меня есть метод, который вызывается из шаблона HTML, он вызывается бесконечно, даже если ничего в моемизменения компонентов.

Проблема

У меня есть страница, похожая на календарь, которая загружает много данных и должна что-то вычислять перед рендерингом,потому что это было бы слишком сложно сделать с директивой ngIf.Поэтому в моем шаблоне есть вещи, которые выглядят следующим образом:

<div [innerHTML]="_getDayPrice(item, day) | safeHtml"></div>  

Если я что-то консолью регистрирую в методе _getDayPrice, печатается бесконечно .

То, что я пробовал

  1. Мне удалось обойти это, вручную вставив ChangeDetectionRef в мое приложение и выполнив this.cdRef.detach().Это, однако, кажется хакерским, так как иногда мне может понадобиться снова включить его и отключить снова.

  2. Я пытался выяснить, является ли это чем-то из моих приложений родительских компонентов, таких как контейнеры.Я создал в моем главном app.component один элемент div, такой как <div class={{computeClass()}}>, и в этом методе напечатал консольный журнал и, конечно, он вызывается бесконечно.После этого я попытался закомментировать все сервисы приложений.Если все закомментированы достаточно точно, это работает правильно, но также нет никаких наблюдаемых данных.Я исследовал около полдня и не смог найти ни одной точки отказа (например, комментирование этого сервиса исправляет все).

  3. Запись производительности с помощью встроенной вкладки «Производительность» Chrome, но опять не смог найти ничего из моего кода, который вызывает изменения.zone.js вызывается несколько раз и, кажется, устанавливает интервал, который продолжает срабатывать.

  4. Конечно, я искал случаи setTimeout и setInterval в службах, но не смогне могу найти что-то, что постоянно меняется, что может вызвать эту проблему.

Заключение?

Итог: нормально ли это, если у вас естьсложное приложение Angular и вызов метода из шаблона, чтобы этот метод вызывался бесконечно?

А если нет, есть ли у вас какие-либо подсказки относительно того, что может быть причиной этого?Или каким-либо другим способом обойти это, а не отключать детектор changeRef?

Моя единственная проблема - производительность.Это похожая на календарь страница, отображающая несколько строк, и она довольно сильно отстает на ноутбуке с 8 ГБ ОЗУ.Я почти уверен, что планшет или телефон почти замерзнут.

Ответы [ 2 ]

0 голосов
/ 25 июня 2018

Вы должны использовать каналы как можно чаще при преобразовании данных в HTML.

Трубы переоцениваются только при изменении объекта или параметров конвейера (поэтому, если один из входных данных является объектом, убедитесь, чтосоздать новый экземпляр этого объекта для запуска переоценки).В большинстве случаев вы можете использовать трубу, а не функцию.

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'getDayPrice'
})
export class GetDayPricePipe implements PipeTransform {

  transform(item: string, day: string): string {
    // ... do whatever logic here
    return item + day;
  }

}

Затем используйте ее так:

<div [innerHTML]="item | getDayPrice:day | safeHtml"></div>
0 голосов
/ 25 июня 2018

Существует два доступных механизма для уменьшения количества проверок привязок.

1 - ChangeDetectorRef.detach : разрешить отсоединение ваших компонентов от цикла обнаружения изменений, поэтому ставки пока не будутобновляется до повторного присоединения.

2 - ChangeDetectionStategy.OnPush : сообщить Angular, что привязки вашего компонента необходимо проверять только тогда, когда хотя бы один из компонентов @Input был изменен.Вы можете найти подробную информацию о том, как его использовать здесь

IMO, вам нужно создать компонент с входами item / days, обертывающими ваш элемент DOM дисплея.Что-то вроде

// wrap.component.ts
@Component({
  template: '<div [innerHTML]="_getDayPrice() | safeHtml"></div>',
  changeDetection: ChangeDetectionStrategy.OnPush,
  ...
})
export class WrapComponent {
  @Input() item: Item;
  @Input() day: String; 

  private _getDayPrice = () => {
      // compute your HTML with this.item and this.day instead of parameters
      ....
  }
}

Тогда вы должны увидеть, как логика срабатывает только при изменении предмета или дня.

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