Angular рендеринг, когда пользователь наводит курсор на карту Openlayers - PullRequest
0 голосов
/ 08 февраля 2020

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

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

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

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

Спасибо.

1 Ответ

3 голосов
/ 08 февраля 2020

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

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

Во-вторых, поскольку базовая библиотека карт (OpenLayers) присоединяет события к самим узлам DOM, это приведет к срабатыванию обнаружения изменений Angular из-за зоны. 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, но здесь это имеет смысл сделать это, чтобы предотвратить ваши проблемы. Вам нужно будет обернуть любые логики c в обработке событий вашей карты обратно в зону 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.

...