Angular Lifecycle Hook

5 min read

Trong thế giới của Angular, việc hiểu rõ về “Life Cycle Hook” là một phần quan trọng trong việc phát triển ứng dụng web. Đây là các phương thức mà Angular cung cấp để chúng ta có thể can thiệp vào quá trình “vòng đời” của một component. Bằng cách này, chúng ta có thể thực hiện các hành động cần thiết tại các điểm khác nhau trong quá trình mà component được tạo ra, cập nhật, hoặc bị hủy bỏ.

Tổng quát life cycle của một component

Constructor

Là phương thức mặc định của class được thực khi class đó được khởi tạo. Nó nên được dùng để khai báo Dependency Injection, không nên xử lí logic ở trong phương thức này

export class TicketModalComponent implements OnInit, OnDestroy, OnChanges {
  public hihi: string = '';
  constructor(
    private heheService: HeheService,
  ) {}

ngOnChanges

ngOnChanges: Được gọi sau khi Angular xử lý các dữ liệu đầu vào của component (input properties) và trước khi gửi chúng cho lần đầu tiên.

import { Component, Input, SimpleChanges, OnChanges } from '@angular/core';

@Component({
  selector: 'app-example',
  template: `...`,
})
export class ExampleComponent implements OnChanges {
  @Input() data: any;

  ngOnChanges(changes: SimpleChanges) {
    if(changes['data'].currentValue !== changes['data'].previousValue) {
      // Handle the data change here
    }
  }
}

Tuy nhiên với các Input có type là Object hoặc Array thì khi thay đổi 1 property hoặc push một phần tử vào mảng đó thì ngOnChange sẽ không chạy, trường hợp này nó chỉ chạy khi các bạn thay đổi reference của biến Input.

this.data = Object.assign({}, this.data);
this.array = [...this.arrayValue];
//hoặc có thể dùng phương thức clone của thư viện lodash
this.data = _.clone(this.data);

Lưu ý nếu component không có các Input thì ngOnChanges sẽ không chạy nhé các bạn

ngOnInit

ngOnInit: Được gọi khi Angular hoàn tất việc khởi tạo component. Thích hợp cho việc thực hiện các tác vụ khởi tạo, như gọi các service để lấy dữ liệu.

Phương thức này sẽ được gọi duy nhất một lần khi khởi tạo xong Component. Ở đây được sử dụng để khởi tạo bổ sung thêm cho component như là khởi tạo giá trị cho biến, gọi api, khởi tạo form, …

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-example',
  template: `...`,
})
export class ExampleComponent implements OnInit {
  constructor() {
    // ...
  }

  ngOnInit() {
    // Initialization logic here
  }
}

Thứ tự thực thi case Parent/Child components

Khi khởi tạo thì component cha phải được khởi tạo trước, sau đó mới đến component con vậy nên ngOninit của component cha sẽ chạy trước component con nhé các fen !!!

ngAfterViewInit

Hook ngAfterViewInitđược gọi khi các khung nhìn của thành phần và các khung nhìn con đã được khởi tạo đầy đủ. Nó thường được sử dụng để sửa đổi DOMhoặc thực hiện các tác vụ hậu kết xuất khác.

Nếu bạn cần chọn các thành phần thông qua ViewChildhoặc ViewChildrentrang trí, đây là móc vòng đời bạn nên sử dụng vì nó đảm bảo rằng các thành phần có sẵn trong mẫu của thành phần.

import { Component, AfterViewInit, ViewChild } from '@angular/core';

@Component({
  selector: 'app-example',
  template: `...`,
})
export class ExampleComponent implements AfterViewInit {
  @ViewChild('exampleRef') exampleRef;

  ngAfterViewInit() {
    // The DOM is fully initialized here
    console.log(this.exampleRef);
  }
}

ngOnDestoy

Được gọi 1 lần duy nhất khi Angular hủy component Thường dùng để handle các event, ubsubscribe obseverble khi hủy component

import { Component, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-example',
  template: `...`,
})
export class ExampleComponent implements OnDestroy {
  private _subscription: Subscription;

  ngOnDestroy() {
    // Clean up logic here
    this._subscription.unsubscribe();
  }
}

ngOnDestoy

Hook ngDoCheckđược gọi ngay sau ngOnChangesvà ngOnInittrong mỗi chu kỳ phát hiện thay đổi. Móc này cho phép bạn triển khai các thuật toán phát hiện thay đổi tùy chỉnh của mình cho bất kỳ thay đổi nào Angularkhông hoặc không thể phát hiện. Hook này được gọi thường xuyên, do đó mọi thao tác bên trong hook này phải nhanh và hiệu quả để tránh suy giảm hiệu suất.

import { Component, DoCheck } from '@angular/core';

@Component({
  selector: 'app-example',
  template: `...`,
})
export class ExampleComponent implements DoCheck {
  ngDoCheck() {
    // Custom change detection logic here
  }
}

ngAfterContentInit

Hook ngAfterContentInit vòng đời được gọi sau khi Angular hoàn thành chu trình kiểm tra nội dung đầu tiên, tức là nó đã chiếu nội dung bên ngoài vào chế độ xem của thành phần. Móc này có thể được sử dụng để thực hiện bất kỳ khởi tạo nào liên quan đến nội dung được chiếu.

import { Component, AfterContentInit } from '@angular/core';

@Component({
  selector: 'app-example',
  template: `...`,
})
export class ExampleComponent implements AfterContentInit {
  ngAfterContentInit() {
    // Initialization logic involving projected content
  }
}

NgAfterContentChecked

ngAfterContentChecked vòng đời được gọi sau khi Angular kiểm tra nội dung được chiếu vào thành phần. Nó được gọi sau ngAfterContentInit và mọi ngDoCheck. Bạn có thể sử dụng hook này để phản ứng với những thay đổi trong nội dung của thành phần đang Angular được kiểm tra.

import { Component, AfterContentChecked } from '@angular/core';

@Component({
  selector: 'app-example',
  template: `...`,
})
export class ExampleComponent implements AfterContentChecked {
  ngAfterContentChecked() {
    // React to the content changes
  }
}

NgAfterViewChecked

Hook ngAfterViewCheckedđược gọi sau khi Angular thực hiện phát hiện thay đổi trên chế độ xem của thành phần (và chế độ xem con). Nó được gọi sau ngAfterViewInit và sau mỗi ngAfterContentChecked. Móc này có thể là một nơi hoàn hảo để phản ứng với những thay đổi ảnh hưởng đến chế độ xem thành phần của bạn.

import { Component, AfterViewChecked } from '@angular/core';

@Component({
  selector: 'app-example',
  template: `...`,
})
export class ExampleComponent implements AfterViewChecked {
  ngAfterViewChecked() {
    // React to the view changes
  }
}

Thứ tự thực thi khi các component lồng nhau

Nested Components đấy cá bạn, nói cách khác là các component có quan hệ cha con thì từng thằng nó sẽ chạy life cycle hook của nó thằng nào trước thằng nào sau, sống trên đời phải có thứ tự chứ đúng không my fens, ai cũng dành chạy trước thì có mà toang 😄

Ok, với ngOnit, ngDoCheck thì cha làm trước rồi con mới được làm.
ngDestroy thì thằng con chạy trước, hết tất cả các thằng con thì thằng cha mới tự tử (destroy 😄)
Với ngAfterViewInit và ngAfterViewChecked những thằng con sẽ được chạy trước, sau khi đám đó chạy xong hết thì ông bô (component cha) mới chạy 2 hook đó.

Lưu ý

Với trường hợp component cha các bạn KHÔNG set changeDetection: ChangeDetectionStrategy.OnPush, tức nó Default, tức mỗi lần state của application thay đổi thì component đó sẽ thực thi change detection. Lúc đó sau khi Component cha chạy ngDoCheck, component con sẽ chạy ngDoCheck -> ngAfterContentChecked -> ngAfterViewChecked. Nhưng nếu component cha các bạn set ChangeDetectionStrategy.OnPush, thì trừ khi Input của component cha thay đổi, hoặc xuất hiện event để chạy change detection ở component cha thì component con mới thực thi đoạn hook ở trên, còn không thì sẽ không chạy đâu nhé các bạn. Lý giải cho điều này là khi các bạn set ChangeDetectionStrategy.OnPush tức component cha sẽ không chạy change detection mỗi khi state application thay đổi mà không liên quan đến nó

Tài liệu tham khảo:

https://viblo.asia/p/nhu-the-nao-la-hieu-ve-component-lifecycle-trong-angular-1VgZveyrKAw

https://miloszeljko.com/angular-lifecycle-hooks/

Avatar photo

Leave a Reply

Your email address will not be published. Required fields are marked *