Tiếp tục phần tiếp theo của series Angular trong phát triển ứng dụng web, ở phần 3 này chúng ta sẽ tìm hiểu Lifecycle Hooks một tính năng đặc biệt được Angular cung cấp.
Lifecycle Hooks trong Angular
Móc vòng đời (Lifecycle hooks) cho phép chúng ta kết nối và chạy code tại một sự kiện vòng đời cụ thể của một component hoặc directive.
Angular quản lý các thành phần và chỉ thị cho chúng ta khi nó tạo, cập nhật hoặc xóa chúng. Với lifecycle hooks, chúng ta có thể kiểm soát chúng một cách tốt hơn cho ứng dụng của mình.
Để thực hiện việc quản lý này, chúng ta thêm một số phương thức móc (hook) cụ thể có tiền tố ng vào component hoặc directive của mình. Các hook này được chia thành hai loại: hook cho các component hoặc directive và hook cho các component con.
Trình tự vòng đời
Đây là những hook cho các component hoặc directive, theo thứ tự gọi:
- Constructor
- OnChanges
- OnInit
- DoCheck
- OnDestroy
Và đây là những hook cho các component con của một component:
- AfterContentInit
- AfterContentChecked
- AfterViewInit
- AfterViewChecked
Giờ ta sẽ tạo một ví dụ đơn giản qua một input và button nhé!
Trước tiên ta tạo giao diện html trong app.component.
Tương tự hàm xử lý OnSubmit trong app.component.ts
Sau đó ta khởi tạo thêm một component demo, nơi này chính là chỗ ta sẽ demo các lifecycle hooks chính.
File html trong component demo.
File .ts với import của cac lifecycle hooks mà chúng ta sẽ sử dụng.
Gọi nó trong file html của app.component như thế này.
Và ta có một giao diện đơn giản.
Ta có thể thấy trong console Constructor đã được gọi vì thế ta sẽ bắt đầu với Constructor nhé.
Constructor
Là phương thức mặc định của class 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.
ngOnChanges
Tiếp đến là Onchange ta sẽ cập nhật demo.compont.ts
ngOnChanges kích hoạt sau khi sửa đổi các thành phần lớp bị ràng buộc @Input. Dữ liệu được ràng buộc bởi @Input() decorator đến từ một nguồn bên ngoài. Khi nguồn bên ngoài thay đổi dữ liệu theo cách có thể phát hiện được, nó sẽ chuyển qua thuộc tính @Input một lần nữa.
Khi ta thay đổi input, ngOnChanges sẽ kích hoạt ngay lập tức. Nó cũng kích hoạt khi khởi tạo dữ liệu đầu vào. Hook nhận một tham số tùy chọn thuộc loại SimpleChanges. Giá trị này chứa thông tin về các thuộc tính giới hạn đầu vào đã thay đổi.
ngOnInit
Theo thứ tự ta tiếp tục với ngOnInit, quay lại file .ts nào!
ngOnInit kích hoạt một lần khi khởi tạo thuộc tính giới hạn đầu vào component (@Input). Ví dụ này, hook không kích hoạt khi demo nhận dữ liệu đầu vào. Thay vào đó, nó kích hoạt ngay sau khi dữ liệu hiển thị thành phần app.
Ta có thể thấy value khi ta khởi tạo trong constructor demo có giá trị là “demo” nhưng sau khi cập nhật OnInIt giá trị value đã trở thành “ ” trong app.component.
ngOnInit là hook một-và-thực-hiện. Khởi tạo là mối quan tâm duy nhất của nó.
ngDoCheck
ngDoCheck kích hoạt với mọi chu kỳ phát hiện thay đổi. Phát hiện thay đổi thường xuyên. Thực hiện bất kỳ hành động nào mỗi khi change detecion chạy, nó sẽ phát hiện các sự kiện như DOM(click, hover), setTimeout, setInterval hay XHR Request. ngDoCheck được gọi mỗi khi Angular phát hiện sự thay đổi vậy nên chúng ta cần chú ý khi sử dung vì nó có thể tạo ra các vấn đề về hiệu suất khi triển khai không chính xác.
Sau khi Angular chạy và khi ta thay đổi dữ liệu là tương đương với mỗi vòng thay đổi tiếp theo đó ngDoCheck được chạy.
Tiếp đến là các hook cho các component con
Ta sẽ thêm một thẻ <h1> với data binding là inputText.
ngAfterContentInit
ngAfterContentInit kích hoạt sau khi DOM nội dung của thành phần khởi tạo (tải lần đầu tiên).
Bắt đầu với AppComponent. Để hoàn thành, AppComponent phải render DemoComponent. DemoComponent chiếu nội dung được lồng trong phần tử của nó thông qua phần tử <ng-content></ng-content>. Nội dung được hiển thị kết thúc render và ngAfterContentInit kích hoạt, sau đó DemoComponent kết thúc render rồi AppComponent kết thúc render và ngafterContentInit sẽ không kích hoạt lại.
ngAfterContentChecked
ngafterContentChecked kích hoạt sau mỗi chu kỳ phát hiện thay đổi nhắm mục tiêu DOM. Điều này cho phép các nhà phát triển tạo điều kiện thuận lợi cho cách DOM phản ứng với phát hiện thay đổi. ngafterContentChecked có thể kích hoạt thường xuyên và gây ra các vấn đề về hiệu suất.
ngafterContentChecked cũng kích hoạt trong các giai đoạn khởi tạo của một thành phần. Nó xuất hiện ngay sau ngafterContentInit. ngafterContentChecked có thể kích hoạt lại thông qua phát hiện thay đổi.
ngAfterViewInit
ngAfterViewInit kích hoạt một lần sau khi chế độ xem DOM khởi tạo xong. View luôn tải ngay sau content. ngAfterViewInit sử dụng thông thường là thực thi view query với tham chiếu bằng viewChild hoặc ViewChilden.
ở ví dụ trên render bắt đầu với AppComponent. Để hoàn thành, AppComponent phải kết xuất DemoComponent. DemoComponent chiếu nội dung được lồng trong phần tử của nó thông qua phần tử <ng-content></ng-content>. Content được hiển thị kết thúc render và DemoComponent kết thúc render sau đó ngAfterViewInit kích hoạt và AppComponent kết thúc render tiếp đó ngAfterViewInit sẽ không kích hoạt lại.
ngAfterViewChecked
ngAfterViewChecked kích hoạt sau bất kỳ chu kỳ phát hiện thay đổi nào nhắm vào View của thành phần. Phương thức ngAfterViewChecked cho phép các nhà phát triển hỗ trợ cách phát hiện thay đổi ảnh hưởng đến chế độ xem DOM.
Mỗi một vòng thay đổi cách ngAfterViewChecked sẽ được chạy lại.
ngOnDestroy
Và để kết thúc lifecycle hooks là ngOnDestroy. Nhưng trước tiên ta phải thêm hàm Destroy trong app.compont qua một button trong html. Vì OnDestroy sẽ chỉ được gọi khi một component hoặc directive bị phá hủy.
File app.component.html
File app.component.ts
Và cuối cùng là file demo.component.ts
Ta sẽ có giao diện được render như sau.
Ta có thể thấy OnDestroy chưa chưa được gọi đến nhưng sau khi click nút Destroy.
DemoComponent chuyển false. Chỉ thị cấu trúc *ngIf đánh giá thành false. ngOnDestroy chạy. *ngIf xóa <p></p> của nó. Quá trình này lặp lại bất kỳ số lần nhấp vào nút để chuyển destroy thành false.
Thứ tự thực thi lifecycle hooks khi các component lồng nhau
Khi các component có quan hệ cha con thì từng component sẽ chạy lifecycle hooks của component đó, component nào được gọi trước thì tương tự lifecycle hooks trong component đó được chạy trước. Nhưng với từng hook lại có trình thực thi được định trước như là:
- Với ngOnit, ngDoCheck thì component cha chạy trước rồi tới component con chạy.
- ngDestroy thì thằng con chạy trước, hết tất cả các component con thì mới tới lượt component cha destroy.
- Với ngAfterViewInit và ngAfterViewChecked những component con chạy trước sau đó mới chạy tới component cha.
Tới đây là kết thúc part 3 về lifecycle hooks trong series thú vị này. Cảm ơn các bạn đã đọc và hẹn gặp lại các bạn trong những part tiếp theo 😀