網站搜尋

typescript - 在 HTML 上使用 setter 和 getter 變數(Angular 組件)


我建立了一個簡單的 Angular 元件來測試使用 getter/setter 風格變數的方式:

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  _name = 'Variable Example';
  get name(): string {
    console.log("GET!!!");
    return this._name;
  }

  set name(value:string): void {
    this._name = value;
  }
}

然後,我在 HTML 上使用這個變數:

<p>
  {{ name }}
</p>

我注意到的是,get name() 被呼叫了 4 次(在這裡查看實時情況)

是否有任何最佳實踐規則指出不應在 HTML 元件上使用 getter 和 setters?使用這種方法會有性能問題嗎?

謝謝你!

附註:這不是實際情況,只是我正在做的事情的一個小例子。

答案#1

更新: 現在有了 Signals,這個討論終於可以徹底結束了。使用 computed 取代 getters 和 signal 輸入,保證你可以獲得良好的性能和聲明式代碼。下面我的回答仍然適用於你因某些原因無法使用 signals 的情況,例如使用舊版 Angular、沒有時間重構,或從模板中帶參數的函數調用。

以下是對我非常有用的經驗法則:

  1. 始終使用 OnPush 變更檢測策略以避免不必要的檢查

  2. 始終使用不可變資料,在任何變更時更新整個陣列/物件。如果你不熟悉不可變性,可以查詢 Google,它非常有幫助,對於 OnPush 是必須的。

  3. 永遠不要儲存可以計算的狀態。如果它可以使用例如元件 @Inputs 來計算——那就用 getter。用數學計算一個簡單的 getter 或遍歷一個小型陣列的速度都非常快,並且避免了同步狀態的麻煩。我在 Firefox 中做過基準測試,一個簡單的 getter 遍歷 100 個元素的陣列每秒可以執行 700 萬次。一般來說,getter 並不會成為應用程式的瓶頸,而且它們比在生命週期勾子中更新狀態更容易使用。但請繼續閱讀。

  4. 如果你的計算狀態產生新的 陣列 或 物件 - 始終使用 純管道 以避免不必要的重新計算,因為這是一個更重的操作,不適合用於 getter。

  5. 如果你的 getter 不會改變 - 考慮使用 lazy initialization 模式:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get#Smart_self-overwriting_lazy_getters

  6. 避免使用 ngOnChange,而是應該使用 @Inputs 上的 setter——這樣你的更改會更“直接”地傳播。某個東西改變了——相關的東西會被更新,而不是“副作用式地”去呼叫某個 hook 等待以後執行。除非你需要對多個同時改變的輸入進行反應。

注意: 這些只是我對此事的看法,這些看法是我在過去幾年參與複雜的 Angular 專案中逐步形成的。

你可以在我寫的這篇文章中閱讀更多關於在 Angular 編寫程式碼時採用宣告式方法的內容:https://indepth.dev/compliant-components-declarative-approach-in-angular/

答案#2

你應該避免從模板中調用方法/存取器,因為每當變更檢測運行時,該方法都會被調用。

相反,你應該在類似 ngOnInit 的方法中計算你想要的東西,並將其賦值給一個變數,或者使用管道。

如果你想在每次值變化時進行計算,你應該使用管道,因為它只會在輸入值變化時被調用,而不是每次變更檢測運行時都調用。