[XYZ] [Angular 2] Lifecycle Component
#Mục lục
- [Định nghĩa component] (#whatiscomponent)
- [Vòng đời component] (#vongdoicomponent)
- [Component lifecycle hooks] (#hooks)
- [Lifecycle sequence] (#sequence)
- [Cách dùng] (#use)
- [Thực hành với lifecycle] (#practice)
**peek-a-boo.component.ts**
export class PeekABoo implements OnInit { constructor(private logger: LoggerService) { }// implement OnInit's
ngOnInit
method ngOnInit() { this.logIt(OnInit
); }protected logIt(msg: string) { this.logger.log(
#${nextId++} ${msg}
); } }
Không có directive hoặc component nào sẽ implement tất cả chúng và chỉ một số hooks có ý nghĩa cho các component. Angular chỉ gọi một directive/component phương thức hook nếu chúng được định nghĩa
Dưới đây là một số các phương thức component lifecycle hook
Sử dụng chung cho cả Directive và Component
- ngOnInit: Khởi tạo directive và component sau khi Angular khởi tạo các thuộc tính của dữ liệu ràng buộc
- ngOnChanges: Phản hồi lại sau khi angular cài đặt một thuộc tính dữ liệu ràng buộc. Phương thức nhận một object changes của hiện tại và giá trị trước đó
- ngDoCheck: Phát hiện và thực hiện thay đổi. Được gọi mỗi khi tìm thấy thay đổi
- ngOnDestroy: Thu hồi trước khi Angular hủy bỏ directive/component. Hủy đăng ký observables và tháo gỡ các sự kiện để tránh tốn bộ nhớ
Chỉ với Component
- ngAfterContentInit: Sau khi angular xuất content ra view
- ngAfterContentChecked: Sau khi Angular kiểm tra sự ràng buộc content để xuất content ra view
- ngAfterViewInit: Sau khi Angular tạo ra view của componet
- ngAfterViewChecked: Sau khi Angular kiểm tra ràng buộc dữ liệu trên view
- Constructor là phương thức khởi tạo mặc định của class, thực hiện khi class được khởi tạo.
- NgOnInit là một hook vòng đời, được gọi bởi Angular2 để chỉ rõ Angular đã hoàn thành việc tạo ra component.
- Không nên lấy dữ liệu về khi khởi tạo bởi constructor theo khuyến cáo lập trình thì càng gọn nhẹ càng tốt. Vì vậy, nên sử dụng NgOnInit để lấy dữ liệu vào component ngay sau khi khởi tạo
Ví dụ dưới đây giải thích các thức hoạt động của các lifecycle hooks thông qua một series các ví dụ được biểu diễn bằng các components dưới sự điều khiển của App Component
.
Dưới đây là mô tả ngắn gọn cho các ví dụ nhỏ:
Component | Description |
---|---|
Peek-a-book | Giải thích từng lifecycle hook. Mỗi phương thức hook được in ra trên màn hình |
Spy | Các directives cũng có các lifecycle hook. SpyDirective thể hiện khi các phần tử spies được tạo ra hoặc hủy bỏ, bằng cách sử dụng ngOnInit và ngOnDestroy . Ví dụ này áp dụng SpyDirective cho thẻ div trong ngFor khi lặp các hero bởi SpyComponent
|
OnChanges | Hiểu cách Angular gọi ngOnChanges hook với một changes object mỗi khi một thuộc tính đầu vào của component thay đổi. |
Do Check | Thực hiện phương thức ngDoCheck khi phát hiện thay đổi. Hiểu cách Angular gọi hook này và xem nó thực hiện thay đổi |
AfterView | Thể hiện cách Angular định nghĩa một view. Giải thích phương thức ngAfterViewInit và ngAfterViewChecked
|
AfterContent | Thể hiện cách ánh xạ content ra một component và cách phân biệt các content được ánh xạ từ các view con. Giải thích phương thức ngAfterContentInit và ngAfterContentChecked
|
Counter | Giải thích sự tổ hợp của một component và một directive và từng hooks của nó. Trong ví du này, CounterComponent hiển thị sự thay đổi mỗi khi component cha tăng thuộc tính đầu vào. Trong lúc đó, SpyDirective sẽ được thực hiện để CounterComponet thấy nơi nó đi vào, được khởi tạo và hủy bỏ. |
PeekABooComponent
thể hiện tất các các hooks trong một component. Nó thể hiện cách Angular gọi các hooks được sắp xếp theo thứ tự.
Ảnh dưới thể hiện các trạng thái màn hình sau khi người dùng nhấn vào nút Create
và sau đó nhấn vào nút Destroy
.
Dãy các thông điệp trả lại màn hình sẽ theo thứ tự OnChanges
, OnInit
, DoCheck (3x)
, AfterContentInit
, AfterContentChecked (3x)
, AfterViewInit
, AfterViewChecked (3x)
, and OnDestroy
.
Spy directive này rất đơn giản, nó giải thích cho ngOnInit
và ngOnDestroy
, nó in ra thông điệp đến directive cha là LoggerService
// Spy on any element to which it is applied.
// Usage: <div mySpy>...</div>
@Directive({selector: '[mySpy]'})
export class SpyDirective implements OnInit, OnDestroy {
constructor(private logger: LoggerService) { }
ngOnInit() { this.logIt(`onInit`); }
ngOnDestroy() { this.logIt(`onDestroy`); }
private logIt(msg: string) {
this.logger.log(`Spy #${nextId++} ${msg}`);
}
}
Bạn có thể áp dụng spy
cho các phần tử của component và nó sẽ khởi tạo và hủy bỏ cùng với thời gian giống phần tử được áp dụng. Dưới đây là sự áp dụng cho vòng lặp hero trong thẻ <div>
<div *ngFor="let hero of heroes" mySpy class="heroes">
{{hero}}
</div>
Mỗi spy khởi tạo và hủy bỏ đánh dấu sự sinh ra và biến mất của các thẻ <div>
hero gắn với nó
Sử dụng ngOnInit
với 2 mục đích chính:
- để biểu diễn một sự khởi tạo phức tạp sau construction
- để cài đặt cho một component sau khi Angular cài các biến đầu vào
Các component nên đơn giản và an toàn để xây dựng. Vì vậy, không nên kết nối dữ liệu ở constructor của component. Phương thức ngOnInit
là nơi lí tưởng cho của việc lấy dữ liệu cho một component.
Đặt các phương thức logic trong ngOnDestroy
, các logic này sẽ phải chạy trước khi Angular hủy bỏ directive.
Đây là nơi để giải phóng các tài nguyên không được tự động hủy bỏ như hủy đăng kí từ observables và các sự kiện của phần tử DOM, dừng các thời gian interval, hủy đăng kí tất cả các callback. Nếu dử dụng nó, bạn sẽ tránh bị rơi vào trường hợp tràn bộ nhớ
Angular gọi phương thức ngOnChange
mỗi khi nó phát hiện thay đổi thuộc tính đầu vào của component hoặc directive. Dưới đây là một onChanges
ngOnChanges(changes: {[propertyName: string]: SimpleChange}) {
for (let propName in changes) {
let chng = changes[propName];
let cur = JSON.stringify(chng.currentValue);
let prev = JSON.stringify(chng.previousValue);
this.changeLog.push(`${propName}: currentValue = ${cur}, previousValue = ${prev}`);
}
}
Phương thức ngOnChanges
lấy đối tượng để nối khi mỗi thuộc tính name thay đổi với đối tượng SimpleChange
nắm giữ giá trị hiện tại và giá trị trước đó. Hooks này sẽ lặp đi lặp lại mỗi khi các thuộc tính thay đổi và in chúng ra màn hình.
Ví dụ như OnChangesComponent
có 2 thuộc tính đầu vào hero
và power
@Input() hero: Hero;
@Input() power: string;
Cha của nó OnChangesParentComponent
kết nối với nó như sau:
<on-changes [hero]="hero" [power]="power"></on-changes>
Đây là ví dụ khi người dùng tạo các sự thay đổi:
Các dòng log xuất hiện khi giá trị của thuộc tính power
thay đổi. Nhưng ngOnChanges
không bắt sự thay đổi của hero.name
. Đây là một điều khá bất ngờ.
Angular chỉ gọi hook khi giá trị của thuộc tính đầu vào thay đổi. Giá trị của thuộc tính hero
là tham chiếu của đối tượng hero. Angular không quan tâm khi thuộc tính name
của hero thay đổi. Đối tượng 'hero' tham chiếu không thay đổi, vì vậy, sẽ không có sự thay đổi nào được in ra