angular11源碼探索[DoCheck 生命周期和onChanges區別]


原理圖

直接生成模塊和路由然后定義聲明的模塊

ng g m  one --routing --m=app

組件+模塊+路由+指向的聲明路徑

ng g m two --route=home  --m=app

生命周期 DoCheck 和 onChanges 的區別

當我們傳入數組或者對象的時候,我們會發現子組件的onChanges 檢測不到變化

這時候我們可以用DoCheck 來監控變化了

父組件,當點擊的時候給父組件

export class TwoComponent implements OnInit {
  public arr: Array<any> = ['a', 'b', 'c']
  obj: object = {
    name: 'xxx',
    age: 'bbb'
  };

  constructor() {
  }


  ngOnInit(): void {
  }

  public i: number = 0;

  clickMethod(): void {
    this.arr.push(this.arr.length)
    this.obj[this.i++] = this.i;
  }
}
<button (click)="clickMethod()">++</button>
<app-user [sex]="arr" [videos]="obj"></app-user>

子組件

只要運行更改檢測,就會調用 ngDoCheck()

export class UserComponent implements OnInit,OnChanges,DoCheck {
  @Input('sex') sex;
  @Input('videos') videos;
 // 可以解構拿到需要修改的屬性
  ngOnChanges({sex,videos}: SimpleChanges) {
    console.log(sex);
    console.log(videos);
  }
  ngDoCheck() {
    console.log(this.videos);
  }
}

我們會發現ngOnChanges子組件除了第一次傳遞的時候能監控到變化,當修改的時候監控不到

但是我們會發現ngDoCheck 在修改的時候能監控到對象的變化

ngOnChanges 用於 基本數據類型

ngDoCheck 用於引用數據類型

KeyValueDiffers

KeyValueDiffers是不同地圖差異策略的存儲庫。角內部使用它的指令NgClassNgStyle等等。無論何時,只要結合這些指令值的變化,這些變化體現。為了處理和更新更改,Angular使用KeyValueDiffers

1. KeyValueDiffers可以使用構造函數注入到組件中。

constructor(private kvDiffers: KeyValueDiffers) {} 

2. KeyValueDiffers提供find方法。

    find(kv: any): KeyValueDifferFactory;

kv:傳遞需要檢測以進行更改的對象。
find方法返回KeyValueDifferFactory

3. KeyValueDifferFactory提供工廠KeyValueDiffer。要獲取KeyValueDiffer實例,請KeyValueDifferFactory提供create方法。

    create<K, V>(): KeyValueDiffer<K, V>;

4. KeyValueDiffer與眾不同之處是跟蹤對象隨時間的變化。它具有一種diff計算先前狀態和新對象狀態之間的差異的方法。

    diff(object: Map<K, V>): KeyValueChanges<K, V> | null;

5. KeyValueChanges自上次diff調用該方法以來,將更改保留在映射中。KeyValueChanges有以下方法。
forEachItem:遍歷所有更改。
forEachPreviousItem:迭代已更改的先前項目。
forEachChangedItem:迭代其值已更改的那些項。
forEachAddedItem:遍歷所有添加的項目。
forEachRemovedItem:遍歷所有已刪除的項目。
上述所有KeyValueChanges提供KeyValueChangeRecord項目的方法都是迭代的。

6. KeyValueChangeRecord是表示項目更改信息的記錄。KeyValueChangeRecord具有諸如currentValuepreviousValue。要獲取當前值,我們將其稱為currentValue屬性,並獲取先前值,我們將其稱為previousValue屬性。找到代碼段。

    readonly key: K;
    readonly currentValue: V | null;
    readonly previousValue: V | null;

完整的例子

export class UserComponent implements OnInit, OnChanges, DoCheck {
  @Input('sex') sex;
  @Input('videos') videos;
  public differs

  // 可以解構拿到需要修改的屬性,一般用於基本數據類型
  ngOnChanges({sex, videos}: SimpleChanges) {
    // console.log(sex);
    // console.log(videos);
  }
  ngDoCheck() {
    let mpArray = this.differs.diff(this.sex)
    if (mpArray) {
      // 變化檢測
      mpArray.forEachAddedItem(record => {
        console.log('增加', record);
      })
      mpArray.forEachChangedItem(record => {
        console.log('更改', record);
      })
      mpArray.forEachRemovedItem(record => {
        console.log('刪除', record);
      })
      /*有變動的時候,顯示原始所有值*/
      mpArray.forEachPreviousItem(record => {
        // console.log('之前的',record);
      })
      /*遍歷所有*/
      mpArray.forEachItem(record => {
        // console.log(record);
      })
    }
  }

  constructor(private kvDiffers: KeyValueDiffers) {
  }

  ngOnInit(): void {
    if (this.sex) {
      this.differs = this.kvDiffers.find(this.sex).create()
    }
  }

}

IterableDiffer

跟蹤隨時間變化為可迭代的策略。用於通過NgForOf影響DOM中的等效更改來響應可迭代的更改

在查看IterableDiffer 源碼的時候我們會發現很多部分跟KeyValueDiffers 有重疊性,

內部NgForOf使用了生命周期掛鈎ngOnChangesngDoCheckngOnChanges該指令用於使用集合find實例的方法根據當前集合的類型選擇一個差異IterableDiffersngDoCheck用於將差值應用於集合的當前值。在不同的是要收集與以前的值進行比較,並返回更改列表

有趣的是,差異如何比較集合中的各個值。特別是,它使用值的哪些屬性來區分它們。為此,我們需要看一下TrackByFunction界面

代碼

export interface TrackByFunction<T> {
  (index: number, item: T): any;
}

demo

<div *ngFor="let item of sex;trackBy:indexFn" >{{item}}</div>

sex=['a','b','c']
indexFn(index,item){
    console.log(index,item);
    return index
  }

0 "a"
1 "b"
2 "c"

不同點

iterableDiffer 比較項目序列

KeyValueDiffer 比較字典


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM