Angular перерисовывает, когда пользователь наводит курсор на карту Openlayers

Я использую Openlayers 6 в своем проекте вместе с Angular 8. И до сих пор я замечал, что всякий раз, когда я наводил курсор на карту Openlayers, компонент Angular, в котором расположена карта, перерисовывается.

Мой вопрос в том, как заставить родительский компонент постоянно переставлять рендеринг при наведении курсора. Потому что это тормозит приложение. В моем проекте есть гораздо больший компонент, и из-за этого повторный рендеринг всего сделает само приложение медленнее.

Для этого я создал репо, чтобы продемонстрировать это: https://github.com/petrovichm/angular-openlayers-hover-problem. В этом примере я добавил метод в html, который будет регистрировать, когда он запускается, таким образом давая обзор, сколько раз угловой компонент повторного рендеринга.

Я хотел создать онлайн-запуск с помощью plunker или codeanbox, но когда я делаю этот пример, окно зависает из-за бесконечного цикла повторного рендеринга, что делает их непригодными для использования, этого на самом деле не происходит, когда я запускаю этот проект локально, это происходит только на парить

Спасибо.

1 ответ

Решение

После клонирования вашего репо, чтобы посмотреть на вещи, есть две вещи.

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

Во-вторых, поскольку базовая библиотека карт (OpenLayers) присоединяет события к самим узлам DOM, это приведет к срабатыванию обнаружения изменений Angular из-за того, что zone.js перехватывает обработку событий. Чтобы этого не произошло, вам придется настроить карту вне зоны Angular:

import { ..., NgZone } from '@angular/core';

...
export class AppComponent implements OnInit {
  ...

  construtor(private zone: NgZone) {
  }

  ...

  ngOnInit() {
    this.zone.runOutsideAngular(() => {
      this.map = new Map({ ... });
    });
  }
}

Вы должны быть осторожны при запуске вещей за пределами зоны Angular, но здесь имеет смысл сделать это, чтобы предотвратить ваши проблемы. Вам придется обернуть любую логику обработки событий вашей карты обратно в зону Angular, чтобы Angular знал об обновлениях.

export class AppComponent implements OnInit {
  currentValue = 0;

  ...

  ngOnInit() {
    this.zone.runOutsideAngular(() => {
      this.map = new Map({ ... });
    });

    this.map.on('click', (e) => {
      this.currentValue++; // Angular will not pick up this change because it will run outside of the Angular zone
    });

    this.map.on('click', (e) => {
      this.zone.run(() => {
        this.currentValue++; // Angular will pick up this change because it will run inside the Angular zone
      });
    });
  }
}

Вот хороший пост в блоге, который, я думаю, может помочь понять это: https://netbasal.com/optimizing-angular-change-detection-triggered-by-dom-events-d2a3b2e11d87.

Другие вопросы по тегам