首頁 > web前端 > js教程 > Angular 反應性的下一個改進

Angular 反應性的下一個改進

Mary-Kate Olsen
發布: 2024-11-17 22:19:01
原創
254 人瀏覽過

The next improvement in Angular reactivity

介紹

自 Angular 最新版本以來,在框架內開發了一種新的原始反應系統:訊號!

今天,事後看來,我們意識到某些用例尚未被覆蓋,顯然 Angular 團隊的積極反應將為我們提供幫助來覆蓋這些用例。

這些用例是什麼?將採取哪些解決方案以及如何使用它們?

相對於另一個訊號重置一個訊號的過程

讓我們先說明這個問題。

假設我們有一籃子一定數量的水果。
數量由輸入水果的組件管理。

@Component({
  template: `<button type="button" (click)="updateQuantity()"> 
    {{quantity()}}
    </button>`
})
export class QuantityComponent() {
  fruit = input.required<string>();
  count = signal(1);

  updateQuantity(): void {
    this.count.update(prevCount => prevCount++);
  }
}
登入後複製
登入後複製
登入後複製

如果輸入的水果價格發生變化,則必須重設變數。

一個簡單的解決方案是使用效果

@Component({
  template: `<button type="button" (click)="updateQuantity()"> 
    {{quantity()}}
    </button>`
})
export class QuantityComponent() {
  fruit = input.required<string>();
  quantity = signal(1);

  countEffect(() => {
    this.fruit();
    this.quantity.set(1);
  }, { allowSignalWrites: true })

  updateQuantity(): void {
    this.quantity.update(prevCount => prevCount++);
  }
}
登入後複製
登入後複製

前面的程式碼是不好的做法。為什麼這是一個大問題?

我們需要將 signalWrites 選項設為 true 才能設定信號量。這是由於對給定問題的誤解造成的。
在我們的例子中,我們想要同步兩個變量,在我們的具體化中,這兩個變數是不同步的

櫃檯並不獨立於水果,水果是我們最初的來源。實際上,這裡我們有一個組件狀態,其初始來源是水果,其餘部分是水果的衍生物。

具體化問題如下

@Component({
  template: `<button type="button" (click)="updateQuantity()"> 
    {{fruitState().quantity()}}
    </button>`
})
export class QuantityComponent() {
  fruit = input.required<string>();

  fruitState = computed(() => ({
    source: fruit(),
    quantity: signal(1),
  }));

  updateQuantity(): void {
    this.fruitState().quantity.update(prevCount => prevCount++);
  }
}
登入後複製
登入後複製

這種具體化將水果與其數量緊密聯繫起來。
因此,一旦水果發生變化,計算變數fruitState就會自動重新計算。此重新計算傳回具有數量屬性的對象,該物件是初始化為 1 的訊號。

透過返回訊號,變數可以在點擊時遞增,並在水果變化時簡單地重置。

這是一個相對簡單的設定模式,但我們不能簡化它嗎?

LinkedSignal 函數可以解決這個問題。

隨著 Angular 19 的到來,一個用於計算派生訊號的新函數。

到目前為止,我們已經有了計算函數,但該函數傳回一個 Signal 而不是 WrittableSignal,這在我們之前的數量變數用例中是實用的。

這就是 LinkedSignal 的用武之地。 LinkedSignal,顧名思義,讓您可以將兩個訊號強連結在一起。

如果我們回到先前的情況,這個函數將允許我們簡化程式碼,如下所示:

@Component({
  template: `<button type="button" (click)="updateQuantity()"> 
    {{quantity()}}
    </button>`
})
export class QuantityComponent() {
  fruit = input.required<string>();
  quantity = linkedSignal({ source: fruit, computation: () => 1 });

  updateQuantity(): void {
    this.quantity.update(prevCount => prevCount++);
  }
}
登入後複製
登入後複製

linkedSignal函數定義如下:

linkedSignal(computation: () => D, options?: { equal?: ValueEqualityFn<NoInfer<D>>; }): WritableSignal<D>;

linkedSignal(options: { source: () => S; computation: (source: NoInfer<S>, previous?: { source: NoInfer<S>; value: NoInfer<D>; }) => D; equal?: ValueEqualityFn<NoInfer<D>>; }): WritableSignal<D>;
登入後複製
登入後複製

在第一個定義(「縮寫」定義)中,linkedSignal 函數採用計算函數作為參數和配置物件。

@Component({
  template: `<button type="button" (click)="updateQuantity()"> 
    {{quantity()}}
    </button>`
})
export class QuantityComponent() {
  fruit = input.required<string>();
  count = signal(1);

  updateQuantity(): void {
    this.count.update(prevCount => prevCount++);
  }
}
登入後複製
登入後複製
登入後複製

在前面的範例中,由於計算函數取決於數量訊號,因此當數量變化時,計算函數會重新評估。

在第二個定義中,linkedFunction方法將一個物件作為具有三個屬性的參數

  • 來源:計算函數重新評估所依據的訊號
  • 計算函數
  • 參數物件

與「縮寫」計算函數相反,這裡的計算函數將來源值和「先例」作為參數。

@Component({
  template: `<button type="button" (click)="updateQuantity()"> 
    {{quantity()}}
    </button>`
})
export class QuantityComponent() {
  fruit = input.required<string>();
  quantity = signal(1);

  countEffect(() => {
    this.fruit();
    this.quantity.set(1);
  }, { allowSignalWrites: true })

  updateQuantity(): void {
    this.quantity.update(prevCount => prevCount++);
  }
}
登入後複製
登入後複製

新的資源 API

Angular 19 將引入一個新的 API,用於簡單的資料擷取和查詢狀態(待處理等)、資料和錯誤的檢索。

對於那些稍微熟悉框架的人來說,這個新 API 的工作方式有點像 useRessource 鉤子。

讓我們來看一個例子:

@Component({
  template: `<button type="button" (click)="updateQuantity()"> 
    {{fruitState().quantity()}}
    </button>`
})
export class QuantityComponent() {
  fruit = input.required<string>();

  fruitState = computed(() => ({
    source: fruit(),
    quantity: signal(1),
  }));

  updateQuantity(): void {
    this.fruitState().quantity.update(prevCount => prevCount++);
  }
}
登入後複製
登入後複製

關於此程式碼片段,有幾件事要了解

這段程式碼中有幾點要注意:

  • 預設情況下,載入器將 Promise 作為參數
  • fruitRessource類型是WrittableRessource,這將使我們能夠根據需要在本地修改資料
  • 水果詳細資訊的請求在資源fuitResource建立時直接發送到伺服器
  • this.fruitId() 在加載器中未跟踪,因此如果 FruitId 更改,則不會發送新請求
  • WrittableRessource有一個方法refresh來刷新資料

以下效果將列印這些值

@Component({
  template: `<button type="button" (click)="updateQuantity()"> 
    {{quantity()}}
    </button>`
})
export class QuantityComponent() {
  fruit = input.required<string>();
  quantity = linkedSignal({ source: fruit, computation: () => 1 });

  updateQuantity(): void {
    this.quantity.update(prevCount => prevCount++);
  }
}
登入後複製
登入後複製

如上所述,預設情況下,fruitId 訊號是未追蹤的。

那麼每次這個訊號的值發生變化時如何重新啟動http請求,以及如果fruitId訊號的值發生變化而對上一個請求的回應沒有變化,如何取消上一個請求到了嗎?

資源函數採用另一個名為 request 的屬性。

此屬性將依賴訊號的函數作為其值並傳回其值。

linkedSignal(computation: () => D, options?: { equal?: ValueEqualityFn<NoInfer<D>>; }): WritableSignal<D>;

linkedSignal(options: { source: () => S; computation: (source: NoInfer<S>, previous?: { source: NoInfer<S>; value: NoInfer<D>; }) => D; equal?: ValueEqualityFn<NoInfer<D>>; }): WritableSignal<D>;
登入後複製
登入後複製

如上面的程式碼所示,載入器函數有兩個參數

  • 請求值:這裡是fruitId訊號的值
  • 用於取消 http 要求的 abortController 物件的 signal 屬性值。

因此,如果在 httpRequest 檢索水果詳細資料期間,fruitId 訊號的值會發生變化,則該請求將被取消以啟動新請求。

最後,Angular 也想到了將這個新 api 與 RxJs 耦合的可能性,讓我們能夠從 Rx 運算子的強大功能中受益。

互通性是透過 rxResource 函數實現的,它的定義方式與資源函數完全相同。
唯一的差異是 loader 屬性的回傳類型,它將傳回一個 observable

@Component({
  template: `<button type="button" (click)="updateQuantity()"> 
    {{quantity()}}
    </button>`
})
export class QuantityComponent() {
  fruit = input.required<string>();
  count = signal(1);

  updateQuantity(): void {
    this.count.update(prevCount => prevCount++);
  }
}
登入後複製
登入後複製
登入後複製

這裡不需要abortSignal,當訊號fruitId的值改變時取消先前的請求,隱含在函數rxResource中,行為與switchMap運算子相同。

以上是Angular 反應性的下一個改進的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板