[Angular] Change Detection

Angular會讓View上面的結果與Model的值同步,大部分的時候,我們並不需要去管 change detection怎麼運作的,但是,了解 change detection並在適當的時候選擇對的 change detection strategy,可以增加系統的效能

何時會觸發change detection

  • DOM Events (click, keyup, etc)
  • AJAX Requests
  • Timers (setTimeout(), setInterval())

Zone

Angular透過Zone來監控上述行為的變化

運作原理

Angular在runtime的時候會為每一個component建立一個Change Detector

Change Detector的運行方向是 Top -> Down,在Default模式下,不論是否有改變,仍會繼續往下檢查

而在 OnPush模式下,如果該節點沒有發生異動時,就不會往下檢查了

JS101: Value Types & Reference Types比較

在進入Change Detection Strategy之前,先重新溫習一下Value Types和Reference Type

Value Types (Stack Memory)

包含以下類別

  • string
  • number
  • boolean
  • null
  • undefined

特性

  1. Stack Memory
  2. Immutable
  3. compared by value
  4. copied by value

Reference Types (Heap Memory)

包含以下類別

  • object
  • array
  • function

特性

  1. Heap Memory
  2. mutable
  3. compared by reference
  4. copied by reference

Change Detection Strategies

DefaultOnPush 細節部份,可參考這篇[Angular] ChangeDetectionStrategy

根據上面的運作原理,我們可以針對個別的Change Detector做策略上的設定,例如下面的圖

OnPush

OnPush的設定方法如下列程式碼

1
2
3
4
5
6
7
8
9
10
import { Component, Input, ChangeDetectionStrategy } from '@angular/core';

@Component({
...
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MovieComponent {
@Input() movie;
...
}

當該Component的changeDetection被設定為ChangeDetectionStrategy.OnPush時,這個Component的檢查關注點就只會在 @Input的這個物件上,所以如果想要讓該Component的 DoCheck被觸發,就必須重新指定新的Input Value。

而這裡應用的的原理是,單獨改變Object內的值而不重新給予一個新的Object,在檢查時,將舊object和異動後的object比較後,結果為兩個是同一個object,所以視為無異動(Reference value的特性)

1
2
3
4
5
6
7
8
var obj1 = {title: 'kevin'};
var obj2 = obj1;
obj2.title = 'KEVIN';
console.log(obj1 == obj2);
> true
obj2 = {title: 'KEVIN'};
console.log(obj1 == obj2);
> false

結論

用正確的ChangeDetectionStrategy,減少系統檢查資料異動狀態的次數,就可以大大的提升系統的效能。