Więc mam 300 wystąpień komponentu, który definiuje globalny detektor zdarzeń kliknięcia przez host
własność:
@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!
}
}
Zauważyłem to ogromnie wpływa na wydajność, zajmuje to około 2-3 sekund przetwarzania po każdym kliknięciu wszędzie na document
.
To jest profil procesora JS wykonany w Chrome dla sekwencji: odczekaj ~ 5 sekund, kliknij, odczekaj kilka sekund i zatrzymaj nagrywanie. Kliknięcie to ogromna zielona kolumna na zrzucie ekranu:
Próbowałem odłączyć Detektor zmian na tym komponencie lub nawet na rodzica, ale to nie pomogło. Po prostu komentując linię "(document: click)": "onClickOff($event)",
rozwiązuje problem.
Może to być kwestia struktury lub złego użycia, ale nie jestem pewien, jak zakwalifikować to lub obejść w bardziej dobrej praktyce sposób.
Odpowiedzi:
1 dla odpowiedzi № 1W poniższym kodzie Angular 2.0.0 (końcowy) spowoduje ten sam problem z wydajnością:
ngAfterViewInit() {
document.addEventListener("click", evt => this.evtClickHandler)
}
rejestracja wydarzenia poza "strefą" powinna pomóc:
constructor(zone: NgZone) {
}
ngAfterViewInit() {
this.zone.runOutsideAngular(() => {
document.addEventListener("click", evt => this.offClickHandler(evt))
})
}
Wyjaśnienie
Problem z wydajnością powtórzył się ponownie przy użyciu biblioteki Sortablejs. Nie było to przed ostateczną wersją Angular, ale coś się zmieniło z powodu rejestracji zdarzeń na elementach natywnych.
Dla biblioteki sortablejs zrobiłem to:
this.sortedImages = Sortable.create(el, options)
co spowodowało naprawdę złą wydajność podczas przeciągania elementów:
Rozwiązanie lub obejście tego problemu wygląda następująco:
this.zone.runOutsideAngular(() => {
this.sortedImages = Sortable.create(el, options)
})
gdzie this.zone
jest wstrzykiwany @angular/core/NgZone
. W ten sposób biblioteka rejestruje detektory zdarzeń poza NgZone.
Wysłałem problem na GitHub o tym problemie, ale uznano, że jest to mój błąd w kodowaniu, a nie błąd w Angular. Jednak pojawiły się pewne zmiany między ostatnimi (RC - przed ostatecznymi) wersjami.
Może to być błąd lub (najnowszy) projekt, ale nie mam na to potwierdzenia.