/ / Ogromny wpływ wydajności na kliknięcia hosta dokumentu komponentu (Angular2) - kątowe, kątowe2-dyrektywy

Ogromny wpływ wydajności na kliknięcie dokumentu głównego komponentu (Angular2) - kątowe, kątowe2

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:

Jedno kliknięcie nic reaktywnego

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.

Plunker tutaj

Wydaj GitHub tutaj

Odpowiedzi:

1 dla odpowiedzi № 1

W 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:

wprowadź opis obrazu tutaj

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.