Огромное влияние на производительность при щелчке основного документа компонента (Angular2)
Таким образом, у меня есть 300 экземпляров компонента, который определяет глобальный слушатель события щелчка через host
имущество:
@Component({
selector: 'value-edit',
template: ``,
host: {
"(document: click)": "onClickOff($event)",
},
changeDetection: ChangeDetectionStrategy.OnPush
)
export class ValueEditComponent {
onClickOff(globalEvent) {
// to make sure it doesn't affect performance we keep it EMPTY!
}
}
Я заметил, что это сильно влияет на производительность, занимает около 2-3 секунд обработки после каждого нажатия на document
,
Это профиль процессора JS, созданный в Chrome для последовательности: подождите ~5 секунд, нажмите, подождите несколько секунд и остановите запись. Клик - огромный зеленый столбец на скриншоте:
Я пытался отключить детектор изменений на этом компоненте или даже родительском, но это не помогло. Просто комментируя строку "(document: click)": "onClickOff($event)",
устраняет проблему
Может быть, проблема в фреймворке или неправильном использовании, но я не уверен, как квалифицировать это или обходной путь более практичным способом.
1 ответ
Решение / обходной путь
На Angular 2.0.0 (окончательный) код ниже приведет к той же проблеме производительности:
ngAfterViewInit() {
document.addEventListener('click', evt => this.evtClickHandler)
}
Регистрация события за пределами "зоны" должна помочь:
constructor(zone: NgZone) {
}
ngAfterViewInit() {
this.zone.runOutsideAngular(() => {
document.addEventListener('click', evt => this.offClickHandler(evt))
})
}
объяснение
Проблема с производительностью снова возникла у меня при использовании библиотеки Sortablejs. До финальной версии Angular это было не так, но что-то изменилось из-за регистрации событий на нативных элементах.
Для библиотеки sortablejs я сделал это:
this.sortedImages = Sortable.create(el, options)
что теперь привело к очень плохой производительности при перетаскивании элементов:
Решение или обходной путь идет так:
this.zone.runOutsideAngular(() => {
this.sortedImages = Sortable.create(el, options)
})
где this.zone
вводится @angular/core/NgZone
, Таким образом, библиотека регистрирует прослушиватели событий за пределами NgZone.
Я опубликовал на GitHub вопрос об этой проблеме, но она была признана моей ошибкой при кодировании, а не ошибкой в Angular. Тем не менее, некоторые изменения появились между последними (RC - до финальной) версии.
Так что это может быть ошибка или (последний) дизайн, но у меня нет подтверждения на это.