對Angular中的生命週期鉤子的理解

玉鴦發表於2017-07-30

什麼是生命週期鉤子

  簡單點來說生命週期鉤子就是Angular中一個元件從被建立當銷燬期間的一些有意義的關鍵時刻.這些關鍵時刻在Angular中被Angular核心模組@angular/core暴露出來,賦予了我們在它們發生時採取行動的能力.

有哪些生命週期鉤子

  Angular中從一個元件的建立到銷燬一個有八個生命週期鉤子它們,按照先後順序.它們分別是:

  • ngOnChanges()
  • ngOnInit()
  • ngDoCheck()
  • ngAfterContentInit()
  • ngAfterContentChecked()
  • ngAfterViewInit()
  • ngAfterViewChecked()
  • ngOnDestroy()

  其中:ngOnInit()ngAfterContentInit()ngAfterViewInit()ngOnDestroy()在一個元件的生命週期中只會被呼叫一次,其它的都有可能會被多次呼叫.下面,就讓我們來詳細解列一下這些生命週期鉤子.

ngOnChanges()

  • 當Angular(重新)設定資料繫結輸入屬性時響應。 該方法接受當前和上一屬性值的SimpleChanges物件
  • 當被繫結的輸入屬性的值發生變化時呼叫,首次呼叫一定會發生在ngOnInit()之前。

  ngOnChanges()生命週期的呼叫與一個元件中的輸入屬性有關.

  當在一個元件中使用@Input()定義了一個輸入屬性時.只要這個輸入屬性的值發生了改變.就會觸發ngOnChanges()生命週期鉤子.這個生命週期鉤子被呼叫時會傳入一個SimpleChanges物件,這個物件中包含了輸入屬性當前值和上一值.

@Input()
public name: string;

ngOnChanges(changes: SimpleChanges): void {
  console.log(changes); // name:SimpleChange {previousValue: "a", currentValue: "ab", firstChange: false}
}複製程式碼

  上面是我定義了一個輸入屬性name並將從a它改為ab之後的列印結果,可能你還注意到了列印的結果中還有一個firstChange屬性.它是一個Booleans,表明你是否是第一次改變.

   同時,還有一點需要注意: 你的輸入屬性定義為你引用型別和基本型別的時候其表現結果是不同的.當你的輸入屬性是基本型別時.你的每一次改變都會觸發ngOnChanges()生命週期鉤子,而當你的輸入屬性是引用型別時,你改變你引用型別 當中 的屬性時,並不會觸發ngOnChanges()生命週期鉤子.只有當你將你引用型別資料的指標指向另一塊記憶體地址的時候才會觸發ngOnChanges()生命週期鉤子.

ngOnInit()

  • 在Angular第一次顯示資料繫結和設定指令/元件的輸入屬性之後,初始化指令/元件。
  • 在第一輪ngOnChanges()完成之後呼叫,只呼叫一次。

  ngOnInit()是一個元件的生命週期中一定存在的一個鉤子.它在一個元件被初始化的時候被呼叫.在這個期間,你可以執行一些相應的資料繫結操作.

ngDoCheck()

  • 檢測,並在發生Angular無法或不願意自己檢測的變化時作出反應。
  • 在每個Angular變更檢測週期中呼叫,ngOnChanges()和ngOnInit()之後。

  ngDoCheck()是Angular中的變更檢測機制.它由zone.js來實現的.其行為是隻要你的Angular中的某個元件發生非同步事件.就會檢查整個元件樹,以保證元件屬性的變化或頁面的變化是同步的.所以ngDoCheck()的觸發相當頻繁的.並且是我們無法預料到的.也許我們在頁面上的一個無意識操作,就會觸發幾個甚至幾十個的ngDoCheck()生命週期鉤子.
  所以我們在使用ngDoCheck()生命週期鉤子的時候一定要加上判斷.以避免無用的觸發干擾我們.

ngAfterContentInit()

  • 當把內容投影進元件之後呼叫。
  • 第一次ngDoCheck()之後呼叫,只呼叫一次。
  • 只適用於元件。

  當父元件向子元件投影內容的時.在子元件內會初始化父元件的投影內容,此時會呼叫ngAfterContentInit()生命週期鉤子.在整個元件生命週期中ngAfterContentInit()生命週期鉤子只會呼叫一次.如下所示:

// 父元件
<app-child>
  <p>我是父元件向子元件的投影內容</>
</app-child>


// 子元件 ChildComponent
<div>
  //接受父元件的投影內容
  <ng-content></ng-content>
</div>複製程式碼

ngAfterContentChecked()

  • 每次完成被投影元件內容的變更檢測之後呼叫。
  • ngAfterContentInit()和每次ngDoCheck()之後呼叫
  • 只適合元件。

  當父元件向子元件的投影內容發生改變時會呼叫ngAfterContentChecked()生命週期鉤子.它與ngDoCheck()類似.當投影內容發生改變時,就會執行變更檢查機制.同時呼叫ngAfterContentChecked()生命週期鉤子.此外.還有一點:當父元件和子元件都有投影內容時,會先執行父元件的生命週期鉤子.它與下面要說的ngAfterViewInit()ngAfterViewChecked()相反.

ngAfterViewInit()

  • 初始化完元件檢視及其子檢視之後呼叫。
  • 第一次ngAfterContentChecked()之後呼叫,只呼叫一次。
  • 只適合元件。

  當其元件本身和所有的子元件渲染完成,已經呈現在頁面上時,呼叫ngAfterViewInit()生命週期鉤子.在整個元件生命週期中ngAfterViewInit()生命週期鉤子只會呼叫一次.

ngAfterViewChecked()

  • 每次做完元件檢視和子檢視的變更檢測之後呼叫。
  • ngAfterViewInit()和每次ngAfterContentChecked()之後呼叫。
  • 只適合元件。

  當元件及其子元件的檢視發生改變時,執行完變更檢查機制後呼叫.當父元件和子元件都發生檢視變化時,會先執行子元件的生命週期鉤子.

  注意: 這裡所說的檢視發生改變不一定是真正頁面上的變化.只是Angular種所認為的檢視變化.因為Angular本身並不能察覺到頁面上顯示的檢視.所以在Angular認為,只要你在後臺定義的屬性發生了改變,就是檢視有了變化.從而就會呼叫ngAfterViewChecked()生命週期鉤子.

ngOnDestroy

  • 當Angular每次銷燬指令/元件之前呼叫並清掃。 在這兒反訂閱可觀察物件和分離事件處理器,以防記憶體洩漏。
  • 在Angular銷燬指令/元件之前呼叫。

我的個人網址: www.wangyiming19950222.com

相關文章