DoCheck wykrywanie zminan - Angular i ngDoCheck
W tym wpisie zrobię szybkie wprowadzenie do ngDoCkeck
. Na początek dowiemy się czym jest ten angularowy hook i kiedy jest wywoływany, a także co takiego robi przy standardowym użyciu.
Do artykułu stworzyłem przykład: https://stackblitz.com/edit/angular-docheck-przyklad
Kiedy ngDoCheck jest uruchamiany?
Hook ngDoCheck
w czasie tworzenia komponentu jest uruchamiany jako trzeci w kolejności, jeśli chodzi o lifecycle hook Angulara. Najpierw ngOnChanges
potem ngOnInit
a na końcu ngDoCheck
. Sam konstruktor jak pamiętamy uruchamia się zawsze jako pierwszy, ale nie należy on do lifecycle hook.
Dodatkowo uruchamia się za każdym razem gdy uruchomi się Change Detection w Angularze. Może więc uruchomić się w naszym komponencie wielokrotnie. Mało tego, jeżeli coś wydarzy się w naszym komponencie, hook ten uruchamiany jest także we wszystkich child komponentach.
Co robi ngDoCheck?
Ja już wiemy ngDoCheck
uruchamia się za każdym razem gdy uruchomi się Change Detection. Dlatego hook ten może nam posłużyć do zaimplementowania własnego wykrywania zmian.
Aby móc posługiwać się ngDoCheck
musimy implementować interfejs DoCheck
:
export class ChildComponent DoCheck { // Uruchomi się zawsze z Change Detection ngDoCheck(): void { console.log('Uruchamiam się zawsze :)') } }
Generalnie Change Detection w Angularze działa przez porównywanie referencji jeśli chodzi o obiekty i listy. Jeżeli będziemy mieli w komponencie pole @Input
, które reprezentowane jest przez obiekt, możemy mieć problem z wykryciem zmian w takim obiekcie. Jeżeli oczywiście chcemy kontrolować zmiany.
export class ChildComponent DoCheck { @Input() dog: Dog; // Uruchomi się zawsze z Change Detection ngDoCheck(): void { console.log('Uruchamiam się zawsze :)') } }
Do wykrywania zmian w polach @Input
służy ngOnChanges
i tam moglibyśmy oczekiwać na zmiany obiektu. Jeżeli jednak nadrzędny komponent spróbuje zmienić obiekt w ten sposób:
change() { this.dog.name = 'Pluto'; }
Change Detection w Angularze porówna tylko referencję i stwierdzi, że to ten sam obiekt. W tej sytuacji zmienia się tylko pole obiektu, więc Angular traktuje to jako ten sam obiekt i metoda ngOnChanges
nie uruchomi się.
Dopiero stworzenie obiektu od nowa, z nową wartością i ponowne jego przekazanie przez @Input
sprawi, że metoda ngOnChanges
odnotuje tą zmianę. W tym przypadku Change Detection zauważy, że zmienił się obiekt (czyli zmieniła się referencja).
Taki zapis już zadziała:
change() { this.dog = {name: 'Pluto'}; }
Ponieważ ngDoCheck
uruchamia się przy każdym uruchomieniu Change Detection to możemy stworzyć własny change detection, który sprawdzi dokładnie każde pole w obiekcie. Prosta implementacja może wyglądać tak:
ngDoCheck(): void { console.log('Sprawdzam!'); if (this.dogCopy.name !== this.dog.name) { console.log(`Nastąpiła zmiana z ${this.dogCopy.name} na ${this.dog.name}`); this.dogCopy = {...this.dog}; } }
W tym przykładzie musimy trzymać w komponencie dodatkowo kopię obiektu, który chcemy sprawdzać. W taki prosty sposób możemy tworzyć własny change detection w metodzie ngDoCheck
.
Na co uważać przy ngDoChek
Z metodą ngDoCheck
należy uważać i unikać jakichkolwiek skomplikowanych operacji. Metoda ta może wywoływać się wielokrotnie. Dodatkowo, ngDoCheck
uruchamia się w każdym komponencie położonym niżej. Przy dużych aplikacjach i częstym stosowaniu ngDoCheck
, a także wielu eventach, możemy narobić sobie więcej kłopotu niż pożytku.
Wystarczy że użyjemy eventu mousemove
w naszym komponencie i metoda będzie wywoływana przy każdym poruszeniu myszki. Dlatego trzeba podchodzić rozważnie do używania tej metody.
Nie używamy ngDoCheck
razem z ngOnChanges
. Ponieważ może się zdarzyć, że będziemy reagowali dwa razy na jedną zmianę. Dlatego implementację taką trzeba dobrze przemyśleć i albo używać jednej albo drugiej metody.
Gdzie jeszcze używać ngDoCheck
Mój przykład to prosty przykład sprawdzania zmian w obiekcie. Możemy użyć specjalnej klasy KeyValueDiffers
. Opiszę to w innym artykule.
Metoda ngDoCheck
przydaje się także gdy przestawimy Change Detection w Angularze na ChangeDetectionStrategy.OnPush
. Na to także będzie inny wpis.
Wnioski
ngDoCheck
uruchamia się zawsze z Change Detection- możemy go używać do kontrolowania każdej zmiany w komponencie
- w porównaniu do
ngOnChanges
, który nie uruchamia się zawsze - dzięki
ngDoCheck
możemy dowiedzieć się, że nastąpiła jakaś zmiana w komponencie tworząc własny dodatkowy change detection - możemy regować na zmiany w polach
@Input
, których nie wykrywa metodangOnChanges
ngDoCheck
używajmy roztropnie ponieważ może uruchamiać się w komponencie setki razy- przedstawiłem najprostsze
ngDoCheck
i jeszcze będę o nim pisał
Linki
Mój przykład na StackBlitz: https://stackblitz.com/edit/angular-docheck-przyklad