簡體   English   中英

消除Angular ngDoCheck生命周期掛鈎

[英]Debounce Angular ngDoCheck lifecycle hook

我一直在進行一些有關在Angular組件中處理狀態的實驗。

假設我有一個計算成本很高的變量,它取決於其他幾個變量。 我可以編寫一個函數updateVar() ,並在我知道可能會影響它的每個事件上調用它。 通過訂閱。 但是,在5個以上的不同位置調用上述函數時,它不會感到很干燥,也不會很健壯。

因此,反跳DoCheck Angular生命周期掛鈎怎么樣呢?

docheckSubject: Subject<any> = new Subject();
debounced: boolean = false;

constructor(private cd: ChangeDetectorRef) {}

ngOnInit() {
  this.docheckSubject.debounceTime(50).subscribe(
    () => this.ngDoCheckDebounced()
  );
}

ngDoCheck() {
  if (!this.debounced) {
    this.docheckSubject.next();
  } else {
    this.debounced = false;
  }
}

ngDoCheckDebounced() {
  this.debounced = true;
  this.updateVar();
  this.cd.detectChanges();  // needed to reflect update in DOM
}

這是一個小例子

這種方法在我的真實應用中似乎可以正常工作,當然,更多的ngDoCheck()正在發生,並且量角器測試也不會抱怨。 但是我無法擺脫做一個骯臟,不太聰明的黑客的感覺。

:這會咬我嗎? 實際上,我是否完全需要它?

ngDoCheck經常被調用:

https://angular.io/guide/lifecycle-hooks#docheck

This hook is called with enormous frequency—after every change detection cycle no matter where the change occurred.

將此鈎子用於除Angular不知道的變量之外的其他任何東西,以尋找更改檢測是一個壞主意。 (例如,輸入對象更改其屬性之一的值)。 防彈跳有一定幫助,但是您仍然非常頻繁地執行該邏輯,並且在不再需要它時(例如,當debounced == false )將繼續這樣做。

我認為您的解決方案可以使用,但是我認為這種方法的開銷比其他方法差得多。 可能有必要將更新邏輯作為Observable鏈的一部分,或者將Observables傳遞到將這種邏輯添加到鏈中的函數中。

經過幾個月沒有問題的生產(AFAICT),我最終刪除了它,因為它最終導致e2e(量角器)測試受阻,直到有人手動單擊頁面。 顯然是不可持續的。

我無法正確診斷此問題的原因,它可能是源於我們代碼中無關部分的怪異現象,但是比后悔更安全。

您能否將變量放入getter中,並且僅在檢索到變量時重新計算?

這是一個簡單的示例:

//our root app component
import {Component, NgModule, VERSION} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello {{name}}</h2>
      <div>x={{x}}</div>
      <div>y={{y}}</div>
      <button (click)="increment()">Increment</button>
      <div>Calculated Value={{calculatedValue}}</div>
    </div>
  `,
})
export class App {
  name:string;
  x: number = 0;
  y: number = 10;

  get calculatedValue(): number {
    return this.x * this.y;
  }

  constructor() {
    this.name = `Angular! v${VERSION.full}`
  }

  increment(): number {
    this.x++;
  }

}

以及相關的Plunker: https ://plnkr.co/edit/QC7mkbsbjRRBjJOjWSHe ? p = preview

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM