@Watch裝飾器:狀態(tài)變量更改通知

2024-01-25 12:07 更新

@Watch應用于對狀態(tài)變量的監(jiān)聽。如果開發(fā)者需要關注某個狀態(tài)變量的值是否改變,可以使用@Watch為狀態(tài)變量設置回調(diào)函數(shù)。

說明

從API version 9開始,該裝飾器支持在ArkTS卡片中使用。

概述

@Watch用于監(jiān)聽狀態(tài)變量的變化,當狀態(tài)變量變化時,@Watch的回調(diào)方法將被調(diào)用。@Watch在ArkUI框架內(nèi)部判斷數(shù)值有無更新使用的是嚴格相等(===),遵循嚴格相等規(guī)范。當在嚴格相等為false的情況下,就會觸發(fā)@Watch的回調(diào)。

裝飾器說明

@Watch補充變量裝飾器

說明

裝飾器參數(shù)

必填。常量字符串,字符串需要有引號。是(string) => void自定義成員函數(shù)的方法的引用。

可裝飾的自定義組件變量

可監(jiān)聽所有裝飾器裝飾的狀態(tài)變量。不允許監(jiān)聽常規(guī)變量。

裝飾器的順序

建議@State、@Prop、@Link等裝飾器在@Watch裝飾器之前。

語法說明

類型

說明

(changedPropertyName? : string) => void

該函數(shù)是自定義組件的成員函數(shù),changedPropertyName是被watch的屬性名。

在多個狀態(tài)變量綁定同一個@Watch的回調(diào)方法的時候,可以通過changedPropertyName進行不同的邏輯處理

將屬性名作為字符串輸入?yún)?shù),不返回任何內(nèi)容。

觀察變化和行為表現(xiàn)

  1. 當觀察到狀態(tài)變量的變化(包括雙向綁定的AppStorage和LocalStorage中對應的key發(fā)生的變化)的時候,對應的@Watch的回調(diào)方法將被觸發(fā);
  2. @Watch方法在自定義組件的屬性變更之后同步執(zhí)行;
  3. 如果在@Watch的方法里改變了其他的狀態(tài)變量,也會引起狀態(tài)變更和@Watch的執(zhí)行;
  4. 在第一次初始化的時候,@Watch裝飾的方法不會被調(diào)用,即認為初始化不是狀態(tài)變量的改變。只有在后續(xù)狀態(tài)改變時,才會調(diào)用@Watch回調(diào)方法。

限制條件

  • 建議開發(fā)者避免無限循環(huán)。循環(huán)可能是因為在@Watch的回調(diào)方法里直接或者間接地修改了同一個狀態(tài)變量引起的。為了避免循環(huán)的產(chǎn)生,建議不要在@Watch的回調(diào)方法里修改當前裝飾的狀態(tài)變量;
  • 開發(fā)者應關注性能,屬性值更新函數(shù)會延遲組件的重新渲染(具體請見上面的行為表現(xiàn)),因此,回調(diào)函數(shù)應僅執(zhí)行快速運算;
  • 不建議在@Watch函數(shù)中調(diào)用async await,因為@Watch設計的用途是為了快速的計算,異步行為可能會導致重新渲染速度的性能問題。

使用場景

@Watch和自定義組件更新

以下示例展示組件更新和@Watch的處理步驟。count在CountModifier中由@State裝飾,在TotalView中由@Prop裝飾。

  1. @Component
  2. struct TotalView {
  3. @Prop @Watch('onCountUpdated') count: number;
  4. @State total: number = 0;
  5. // @Watch 回調(diào)
  6. onCountUpdated(propName: string): void {
  7. this.total += this.count;
  8. }
  9. build() {
  10. Text(`Total: ${this.total}`)
  11. }
  12. }
  13. @Entry
  14. @Component
  15. struct CountModifier {
  16. @State count: number = 0;
  17. build() {
  18. Column() {
  19. Button('add to basket')
  20. .onClick(() => {
  21. this.count++
  22. })
  23. TotalView({ count: this.count })
  24. }
  25. }
  26. }

處理步驟:

  1. CountModifier自定義組件的Button.onClick點擊事件自增count。
  2. 由于@State count變量更改,子組件TotalView中的@Prop被更新,其@Watch('onCountUpdated')方法被調(diào)用,更新了子組件TotalView 中的total變量。
  3. 子組件TotalView中的Text重新渲染。

@Watch與@Link組合使用

以下示例說明了如何在子組件中觀察@Link變量。

  1. class PurchaseItem {
  2. static NextId: number = 0;
  3. public id: number;
  4. public price: number;
  5. constructor(price: number) {
  6. this.id = PurchaseItem.NextId++;
  7. this.price = price;
  8. }
  9. }
  10. @Component
  11. struct BasketViewer {
  12. @Link @Watch('onBasketUpdated') shopBasket: PurchaseItem[];
  13. @State totalPurchase: number = 0;
  14. updateTotal(): number {
  15. let total = this.shopBasket.reduce((sum, i) => sum + i.price, 0);
  16. // 超過100歐元可享受折扣
  17. if (total >= 100) {
  18. total = 0.9 * total;
  19. }
  20. return total;
  21. }
  22. // @Watch 回調(diào)
  23. onBasketUpdated(propName: string): void {
  24. this.totalPurchase = this.updateTotal();
  25. }
  26. build() {
  27. Column() {
  28. ForEach(this.shopBasket,
  29. (item) => {
  30. Text(`Price: ${item.price.toFixed(2)} €`)
  31. },
  32. item => item.id.toString()
  33. )
  34. Text(`Total: ${this.totalPurchase.toFixed(2)} €`)
  35. }
  36. }
  37. }
  38. @Entry
  39. @Component
  40. struct BasketModifier {
  41. @State shopBasket: PurchaseItem[] = [];
  42. build() {
  43. Column() {
  44. Button('Add to basket')
  45. .onClick(() => {
  46. this.shopBasket.push(new PurchaseItem(Math.round(100 * Math.random())))
  47. })
  48. BasketViewer({ shopBasket: $shopBasket })
  49. }
  50. }
  51. }

處理步驟如下:

  1. BasketModifier組件的Button.onClick向BasketModifier shopBasket中添加條目;
  2. @Link裝飾的BasketViewer shopBasket值發(fā)生變化;
  3. 狀態(tài)管理框架調(diào)用@Watch函數(shù)BasketViewer onBasketUpdated 更新BasketViewer TotalPurchase的值;
  4. @Link shopBasket的改變,新增了數(shù)組項,F(xiàn)orEach組件會執(zhí)行item Builder,渲染構建新的Item項;@State totalPurchase改變,對應的Text組件也重新渲染;重新渲染是異步發(fā)生的。
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號