Angular - haki cyklu życia komponentu (lifecycle hooks)

Stronę tą wyświetlono już: 24 razy

Wstęp

Angular dysponuje metodami, które w określonym cyklu życia komponentu (lifecycle hooks) są uruchamiane. Aby jednak to mogło nastąpić trzeba najpierw zadeklarować w komponencie klasy odpowiednią metodę. I tutaj Angular wymyślił specjalne interfejsy, które po zaimplementowaniu w deklaracji klasy komponentu wymuszają obsługę odpowiedniej funkcji. Nie jest to wymagane, ale niektóre dodatki płaczą o dodanie implementacji tego interfejsu co jest nieco pozbawione sensu, gdyż i tak trzeba wiedzieć jakiej metody użyć, aby w danym cyklu życia komponentu móc wykonać określoną operację.

ngOnInit

ngOnInit jest to metoda klasy wywoływana automatycznie tylko raz gdy po raz pierwszy Angular wyświetli powiązane dane i właściwości oraz ustawi wartości wejściowe komponentu.

Angular udostępnia specjalne interfejsy, po których implementacji wymusza automatycznie obsługę danego haka. Dla ngOnInit będzie to interfejs OnInit. Oto przykład użycia tego haka:

Listing 1
  1. export class myFirstComponent implements OnInit {
  2. @Input()
  3. title: string = '';
  4. constructor() { }
  5. ngOnInit() {
  6. this.title = 'Tytuł strony: ' + this.title;
  7. }
  8. logIt(msg: string) {
  9. this.logger.log(`#${nextId++} ${msg}`);
  10. }
  11. }

ngOnDestroy

Gdy komponent jest niszczony czasem trzeba zrobić parę innych rzeczy, zanim to nastąpi. I tutaj z odsieczą biegnie na pomoc hak o nazwie ngOnDestroy.

Listing 2
  1. ngOnDestroy() {
  2. console.log('Komponent zniszczony');
  3. }

Oczywiście Angular ma do wymuszania obsługi tego haka interfejs OnDestroy.

ngOnChanges

Gdy jakaś zmienna wejściowa komponentu ulega zmianie, ta metoda zostanie wywołana z jednym parametrem zawierającym dane dotyczące zmian, jakie zostały wykryte. Oto przykład:

Listing 3
  1. @Input()
  2. title: string = '';
  3. ngOnChanges(changes: SimpleChanges) {
  4. for (let name in changes) {
  5. const changes = changes[propName];
  6. const current = JSON.stringify(chng.currentValue);
  7. const previous = JSON.stringify(chng.previousValue);
  8. console.log(`${name}: Wartość bieżąca = ${current}, wartość poprzednia = ${previous}`);
  9. }
  10. }

W tym przypadku klasa może zostać rozszerzona o interfejs OnChanges. Jeżeli w kodzie klasy jakaś zmienna podpięta pod kontrolkę ulegnie zmianie, hak ngOnChanges zostanie wywołana automatycznie podając nazwę zmiennej, jej wartość przed i po modyfikacji.

ngOnCheck

Ten hak uruchamiany jest zaraz po ngOnInit oraz gdy uruchamia się detektor zmian. Rozszerza on działanie ngOnChange, który reaguje jedynie na zmianę referencji obserwowanego obiektu, nie zaś na zmianę jego właściwości.

Listing 4
  1. @Input()
  2. student: { name: 'Grzegorz', surname: 'Brzęczyszczykiewicz' };
  3. ngOnCheck() {
  4. if (this.student.name !== 'Grzegorz') {
  5. console.log(this.student.name, ' !== "Grzegorz"');
  6. }
  7. }

W Angular-ze istnieje interfejs ngOnCheck wymuszający obsłużenie tego haka, nie jest on jednak tak na prawdę wymagany.

ngAfterViewInit

Każdy komponent jest połączony z plikiem HTML lub okrojonym jego szablonem. Zanim widok i całe drzewo dokumentu DOM się wyrenderuje potrzebna jest dłuższa lub krótsza chwila. Zdarza się, że ta chwila następuje po ustawieniu zmiennych komponentu, przez co niektóre dane mogą się nie wyświetlać lub niektóre komponenty mogą nie działać prawidłowo. Z odsieczą przybywa tutaj hak ngAfterViewInit, który jest odpalany gdy widok strony zostanie wyrenderowany.

Listing 5
  1. @ViewChild('element', {static: true}) element: ElementRef; // przechwytywanie elementu HTML komponentu, które nastąpi po załadowaniu widoku
  2. constructor() {
  3. console.log('constructor', element);
  4. }
  5. ngOnAfterViewInit() {
  6. console.log('ngOnAfterViewInit', element);
  7. }

W kodzie HTML wystarczy umieścić taki oto element:

Listing 6
  1. <div #element>Przykładowy element HTML przechwytywany za pomocą dekoratora <strong class="Angular decorator">ViewChild</strong></div>

Wynik w konsoli przeglądarki będzie wyglądał następująco:

constructor undefined
ngOnAfterViewInit Object { nativeElement: div.example }

ngAfterViewChecked

Tej hak Angular-owy uruchamiany jest po wygenerowaniu widoku komponentu oraz gdy nastąpi zmiana widoku komponentu.

Listing 7
  1. ngOnAfterViewChecked() {
  2. console.log('ngAfterViewChecked');
  3. }

ngAfterContentInit

Tworząc komponent i osadzając go wewnątrz innego komponentu można pomiędzy jego znacznikami zamieścić dodatkową zawartość, które domyślnie nie zostanie osadzona wewnątrz komponentu. Oto przykład:

Listing 8
  1. <app-my-first><div>Jakiś dodatkowy komponent zewnętrzny</div></app-my-first>

Element osadzony wewnątrz komponentu MyFirstComponent nie zostanie wyświetlony w jego wnętrzu chyba, że w jego wnętrzu użyta zostanie dyrektywa ng-content w następujący sposób:

Listing 9
  1. <div>Jakiś wewnętrzny element komponentu</div>
  2. <ng-content></ng-content>
  3. <div>Kolejny wewnętrzny element komponentu</div>

Hak ngAfterContentInit jest uruchamiany, gdy zawartość elementów pochodzących z komponentu nadrzędnego zostanie zainicjalizowana.

Listing 10
  1. ngAfterContenInit() {
  2. console.log('ngAfterConentInit');
  3. }

ngAfterContentChecked

Ten hak również dotyczy elementów pochodzących z nadrzędnego komponentu, które zostały osadzone w jego wnętrzu. Jest on uruchamiany zaraz po haku ngAfterContentInit oraz za każdym razem, gdy nastąpi zmiana w tychże elementach.

Listing 11
  1. @ContentChild('childComponent', {static: false}) childComponent: ElementRef;
  2. ngAfterContentChecked() {
  3. console.log('ngAfterContentChecked', this.childComponent);
  4. }
Powiązane strony:
strony powiązane
  1. angular.io - strona dokumentacji Angulara

Komentarze