Angular - ngOnChanges- Angular LifeCycle Hook (1/2)

  • 1557
  • 0
  • 2018-05-21

介紹 ngOnChanges 基礎用法

ngOnChanges:

觸發的時機點:component如果,

當父類別透過透過Property Binding (屬性繫結)將資料傳到子元件,

子元件透過宣告 @Input() 的變數來接收父類別傳來的資料,

子元件的ngOnChange就會被觸發,

當父類別的來源資料有異動的時候,也會重新觸發 ngOnChanges()

 

執行的先後順序

constructor() => ngOnChanges() => ngOnInit()

範例說明:

建立兩個component : 

ng g c demo-parent

ng g c demo-child

在父元件裡面設定一個要給子元件的參數:counter ,預設是0 過兩秒鐘之後累加一次

export class DemoParentComponent implements OnInit {
  constructor() {}

  counter = 0;

  ngOnInit() {
    setTimeout(() => {
      this.counter++;
    }, 3000);
  }
}

接著在template內透過Property Binding (屬性繫結)將資料傳到子元件

<p>
    demo-parent works!
</p>

<app-demo-child [iCounter]="counter"></app-demo-child>

然後開始改子元件的component.ts

寫 ngOnChanges() 的時候建議可以加入interface OnChanges,這樣打錯字或是 ngOnChanges() 打錯字的錯誤就可避免

新增一個 @Input() iCounter; 

然後依序在三個事件內加入console.log ,可以觀察三個事件的執行先後順序

export class DemoChildComponent implements OnInit, OnChanges {
  @Input() iCounter;

  constructor() {
    console.log('Child component constructor');
  }

  ngOnInit() {
    console.log('Child component ngOnInit');
  }

  ngOnChanges() {
    console.log('Child component ngOnChanges');
  }
}

執行結果如下:

可看到執行先後順序

constructor() => ngOnChanges() => ngOnInit()

因為在父元件那邊有寫了一個 setTimeout 過了三秒鐘累加counter的值

累加之後,子元件的 @Input() iCounter 資料也改變了,所以會在觸發一次 ngOnChanges()事件

 

ngOnChanges()  參數

ngOnChanges() 的參數型態是一個物件,

假設父元件傳遞了兩個以上的 @Input() 到子元件

子元件的 ngOnChanges() 接收到的物件就會有兩個屬性,一個是inItem、一個是inContent

也就是在子元件宣告的 @Input() 名稱

inItem、inContent 這個兩屬性名稱對應的又是另外的物件

物件內的currentValue 才是真正傳進來的值

以下圖為例:inItem 接收的是一個物件、inContent 接收的是一個字串

除了 currentValue  之外還有  firstChangepreviousValue 讓開發人員去判斷是否為第一次變更、上一次的值是什麼

在ngChanges 裡面,可以用判斷 @Input() 變數名稱 的方式來設計要獨立的後續作業

@Input() inItem;
@Input() inContent;

ngOnChanges(changeItems) {
    if (changeItems.inItem) {
      // inItem 要做的事情
      this.OriItem = changeItems.inItem.currentValue;
      this.inItem = Object.assign({}, changeItems.inItem.currentValue);
    }
    if (changeItems.inContent) {
      // inContent 要做的事情
    }
  }