一、view鉤子 view鉤子有2個,ngAfterViewInit和ngAfterViewChecked鉤子。 1、實現ngAfterViewInit和ngAfterViewChecked鉤子時註意事項 以父組件調用子組件方法 中例子為基礎,在父組件中實現ngAfterViewInit和ngAft ...
一、view鉤子
view鉤子有2個,ngAfterViewInit和ngAfterViewChecked鉤子。
1、實現ngAfterViewInit和ngAfterViewChecked鉤子時註意事項
以父組件調用子組件方法 中例子為基礎,在父組件中實現ngAfterViewInit和ngAfterViewChecked鉤子。
這兩個鉤子是在組件的模版所有內容組裝完成後,組件模版已經呈現給用戶看了,之後這兩個鉤子方法會被調用。
@ViewChild('child1') child1:Child1Component; //父組件中獲得子組件的引用 ngOnInit(){ this.child1.greeting("Tom"); } ngAfterViewInit(){ console.log("父組件的視圖初始化完畢"); } ngAfterViewChecked(){ console.log("父組件的視圖變更檢測完畢"); }
在子組件中也實現這兩個鉤子
export class Child1Component implements OnInit,AfterViewInit,AfterViewChecked{ constructor() { } ngOnInit() { } greeting(name: string) { console.log("hello" + name); } ngAfterViewInit(){ console.log("子組件的視圖初始化完畢"); } ngAfterViewChecked(){ console.log("子組件的視圖變更檢測完畢"); } }View Code
在父組件的ngOnInit中不直接調用子組件的greeting()方法,而是通過一個定時器每隔5s去調用一次。
ngOnInit(){ setInterval(()=>{ this.child1.greeting("Tom"); },5000); }
總結:
1、Init先調用,checked後調用
看1中,首先子組件視圖初始化完畢,然後子組件視圖變更檢測完畢。
2、子組件先於父組件被組裝好
看2中,因為父組件中聲明瞭2個子組件,所以看到有2個子組件 初始化的動作。1號子組件初始化完畢,變更檢測完畢,2號子組件初始化完畢,變更檢測完畢後,父組件的初始化完畢才會被調用,然後父組件的變更檢測完畢才會被調用。
3、ngAfterViewInit只會在初始化完畢被調用一次。
4、定時器觸發方法後,兩個子組件的變更檢測會被調用,父組件的變更檢測也會被調用。
視圖沒有發生任何改變,變更檢測也會被調用,實現來ngAfterViewChecked()鉤子的方法都會被調用。
所以ngAfterViewChecked()鉤子一定要寫的精簡以免出現性能問題。
2、在一個變更檢測周期中禁止一個視圖被組裝好之後再去更新視圖
例子:
父組件
有一個message初始化為abc.顯示到模版上。
message:string='abc';在父組件的ngAfterViewInit中更改message值。
ngAfterViewInit(){ console.log("父組件的視圖初始化完畢"); this.message="def"; }
會報錯。ngAfterViewInit()和ngAfterViewChecked()都是在視圖組裝完成後觸發的,所以在這兩個鉤子中更新組件中被綁定的屬性,觸發組件視圖的變化,Angular就會拋出異常。
解決辦法:
把代碼放在另一個時間迴圈裡面。
ngAfterViewInit(){ console.log("父組件的視圖初始化完畢"); setTimeout(()=>{ this.message="def"; },0); }
二、content鉤子
包括2個與投影相關的鉤子,ngAfterContentInit()和ngAfterContentChecked()鉤子。
ngAfterContentInit,ngAfterContentChecked和ngAfterViewInit,ngAfterViewChecked類似。
ngAfterViewInit,ngAfteViewChecked是在整個組件的視圖全部組裝完成後調用的。
ngAfterContentInit,ngAfterContentChecked是在被投影進來的內容組裝完成後調用的。
1、Content鉤子的調用順序例子
父組件中實現ngAfterContentInit,ngAfterContentChecked和ngAfterContentInit()
export class AppComponent implements OnInit, AfterViewInit, AfterContentInit,AfterContentChecked{ ngAfterViewInit(){ console.log("父組件的視圖初始化完畢"); } ngAfterContentInit(){ console.log("父組件投影內容初始化完畢"); } ngAfterContentChecked(){ console.log("父組件投影內容變更檢測完畢"); }
子組件中也實現這3個介面
export class Child2Component implements OnInit,AfterViewChecked,AfterContentInit,AfterContentChecked{ constructor() { } ngOnInit() { } ngAfterViewInit(){ console.log("子組件的視圖初始化完畢"); } ngAfterContentInit(){ console.log("子組件投影內容初始化完畢"); } ngAfterContentChecked(){ console.log("子組件投影內容變更檢測完畢"); } }
組裝視圖時,先組裝投影進來的內容,然後組裝子組件中視圖的內容,再加上父組件本身的內容,然後才是父組件視圖初始化完畢。
2、Content鉤子中可以修改模版內容
view鉤子里不能修改模版內容,因為模版內容組裝完畢後不能再修改裡面內容。但是Content鉤子里可以。
因為Content鉤子調用時整個視圖還沒有組裝完畢,只是投影進來的內容被組裝完畢了。
父組件中在ngAfterContentInit鉤子里修改message信息不會報錯。
export class AppComponent implements OnInit, AfterViewInit, AfterContentInit,AfterContentChecked{ message:string='abc'; ngAfterViewInit(){ console.log("父組件的視圖初始化完畢"); } ngAfterContentInit(){ console.log("父組件投影內容初始化完畢"); this.message='def'; } ngAfterContentChecked(){ console.log("父組件投影內容變更檢測完畢"); } ngOnInit(){ }View Code
三、總結
上面四個方法在屬性初始化階段:構造函數是初始化對象,ngOnChanges是初始化輸入屬性,ngOnInit是初始化除了輸入屬性以外其它的所有屬性,ngDoCheck是做一次變更檢查。
這四個方法執行完整個組件所有屬性都被賦予了應該被賦的值。
組件開始渲染它的視圖,首先渲染投影進來的內容,投影進來的內容渲染完調用ngAfterContentInit和ngAfterContentChecked鉤子方法。
如果有子組件會調子組件創建的過程,子組件創建完或者沒有子組件,整個組件的視圖都初始化完畢了以後,會調ngAfterViewInit和ngAfterViewChecked鉤子方法。
至此,整個組件初始化完畢,組件會呈現給用戶交互。
用戶交互觸發Angular的變更檢測機制,檢測到發生了變更,在當前組件樹上所有活動組件上被實現的帶有check的鉤子方法都會被調用,用來檢查當前組件的變化,如果變化導致某個組件的輸入屬性也改變了,那個組件的ngOnChanges也會被調用。
組件在路由地址變化從而被銷毀的時候會調ngOnDestory()。
在ngOnDestory中銷毀一些引用的資源,比如反訂閱一個流,清除定時器之類的。
本文作者starof,因知識本身在變化,作者也在不斷學習成長,文章內容也不定時更新,為避免誤導讀者,方便追根溯源,請諸位轉載註明出處:http://www.cnblogs.com/starof/p/8705587.html 有問題歡迎與我討論,共同進步。