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.