<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

HarmonyOS開發實例:【狀態管理】

jf_46214456 ? 來源:jf_46214456 ? 作者:jf_46214456 ? 2024-04-10 09:38 ? 次閱讀

ArkUI開發框架提供了多維度的狀態管理機制,和UI相關聯的數據,不僅可以在組件內使用,還可以在不同組件層級間傳遞,比如父子組件之間,爺孫組件之間等,也可以是全局范圍內的傳遞,還可以是跨設備傳遞。另外,從數據的傳遞形式來看,可以分為只讀的單向傳遞和可變更的雙向傳遞。如下圖所示,開發框架提供了多種應用程序狀態管理的能力。

2_5_1

@State修飾符

@State 裝飾的變量是組件內部的狀態數據,當這些狀態數據被修改時,將會調用所在組件的 build() 方法刷新UI。 @State 狀態數據具有以下特征:

  • 支持多種數據類型:允許 class 、 number 、 boolean 、 string 強類型的按值和按引用類型。允許這些強類型構成的數組,即Array、Array、Array、Array。不允許 objectany。
  • 內部私有:標記為 @State 的屬性是私有變量,只能在組件內訪問。
  • 支持多個實例:組件不同實例的內部狀態數據獨立。
  • 需要本地初始化:必須為所有 @State 變量分配初始值,將變量保持未初始化可能導致框架行為未定義,初始值需要是有意義的值,比如設置 class 類型的值為 null 就是無意義的,會導致編譯報錯。
  • 創建自定義組件時支持通過狀態變量名設置初始值:在創建組件實例時,可以通過變量名顯式指定 @State 狀態屬性的初始值。
    |

簡單樣例如下所示:

@Entry @Component struct ComponentTest {

      @State date: string = "時間:" + new Date().getTime(); // data變化會觸發build方法執行

      build() {
        Column({space: 10}) {

          Text(`父組件【${this.date}】`)                     // 顯示時間
            .fontSize(20)
            .backgroundColor(Color.Pink)

          Item()                                            // 子組件
          Item()                                            // 子組件

          Button('更新時間')
            .onClick(() = > {
              this.date = "時間:" + new Date().getTime();   // 點擊按鈕,date變化,會觸發build方法執行
            })
        }
        .width('100%')
        .height('100%')
        .padding(10)
      }
    }

    // 自定義子組件
    @Component struct Item {

      @State time: string = "時間:" + new Date().getTime();

      build() {
        Text(`子組件【${this.time}】`)
          .fontSize(20)
          .backgroundColor(Color.Grey)
          .onClick(() = > {
            this.time = "時間:" + new Date().getTime();     // 點擊更新時間,執行build方法
          })
      }
    }

樣例運行結果如下圖所示:

2_5_1_1

@Prop修飾符

開發應用知識已更新[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md]參考前往。

@Prop@State 有相同的語義,但初始化方式不同, @Prop 裝飾的變量可以和父組件的 @State 變量建立單向的數據綁定。即 @Prop 修飾的變量必須使用其父組件提供的 @State 變量進行初始化,允許組件內部修改 @Prop 變量值但更改不會通知給父組件。 @Prop 狀態數據具有以下特征:

  • 支持簡單數據類型:僅支持 number 、 string 、 boolean 簡單類型;

  • 內部私有:標記為 @Prop 的屬性是私有變量,只能在組件內訪問。

  • 支持多個實例:組件不同實例的內部狀態數據獨立。

  • 不支持內部初始化:在創建組件的新實例時,必須將值傳遞給 @Prop 修飾的變量進行初始化,不支持在組件內部進行初始化。
    簡單樣例如下所示:

    @Entry @Component struct ComponentTest {
    
      @State date: string = "時間:" + new Date().getTime();
    
      build() {
        Column({space: 10}) {
    
          Text(`父組件【${this.date}】`)
            .fontSize(20)
            .backgroundColor(Color.Pink)
    
          Item({time: this.date})                        // 必須初始化子組件的time字段
          Item({time: this.date})                        // 必須初始化子組件的time字段
    
          Button('更新時間')
            .onClick(() = > {
              this.date = "時間:" + new Date().getTime();// 父組件的更改影響子組件
            })
        }
        .width('100%')
        .height('100%')
        .padding(10)
      }
    }
    
    @Component struct Item {
    
      @Prop time: string;                                // 不允許本地初始化
    
      build() {
        Text(`子組件【${this.time}】`)
          .fontSize(20)
          .backgroundColor(Color.Grey)
          .onClick(() = > {
            this.time = "時間:" + new Date().getTime();  // 子組件的更改不影響父組件
          })
      }
    
    }
    

    樣例運行結果如下圖所示:

    2_5_2_1

@Link修飾符

@Link@State 有相同的語義,但初始化方式不同, @Link 裝飾的變量可以和父組件的 @State 變量建立雙向的數據綁定。即 @Link 修飾的變量必須使用其父組件提供的 @State 變量進行初始化,允許組件內部修改 @Link 變量值且更改會通知給父組件。 @Link 狀態數據具有以下特征:

  • 支持多種數據類型: @Link 變量的值與 @State 變量的類型相同,即 class 、 number 、 string 、 boolean 或這些類型的數組。
  • 內部私有:標記為 @Link 的屬性是私有變量,只能在組件內訪問。
  • 支持多個實例:組件不同實例的內部狀態數據獨立。
  • 不支持內部初始化:在創建組件的新實例時,必須將值傳遞給 @Link 修飾的變量進行初始化,不支持在組件內部進行初始化。初始化使用 $ 符號,例如:$propertiesName。

樣例如下:

@Entry @Component struct ComponentTest {

  @State date: string = "時間:" + new Date().getTime(); // 定義@State變量

  build() {
    Column({space: 10}) {

      Text(`父組件【${this.date}】`)
        .fontSize(20)
        .backgroundColor(Color.Pink)

      Item({time: $date})                               // 初始化子組件time屬性使用$符號
      Item({time: $date})                               // 初始化子組件time屬性使用$符號

      Button('更新時間')
        .onClick(() = > {
          this.date = "時間:" + new Date().getTime();   // 變更date,子組件的對應屬性也變化
        })
    }
    .width('100%')
    .height('100%')
    .padding(10)
  }
}

@Component struct Item {

  @Link time: string;

  build() {
    Text(`子組件【${this.time}】`)
      .fontSize(20)
      .backgroundColor(Color.Grey)
      .onClick(() = > {
        this.time = "時間:" + new Date().getTime();     // 變更time,父組件的對應屬性也變化
      })
  }
}

樣例運行結果如下圖所示:

2_5_3_1

@StorageLink修飾符

@StorageLink(key) 裝飾的變量是組件內部的狀態數據,當這些狀態數據被修改時,將會調用所在組件的 build() 方法進行UI刷新。組件通過使用 @StorageLink(key) 裝飾的狀態變量與 AppStorage 建立雙向數據綁定。當創建包含 @StorageLink 的狀態變量的組件時,該狀態變量的值將使用 AppStorage 中的值進行初始化,在UI組件中對 @StorageLink 的狀態變量所做的更改將同步到 AppStorage ,并從 AppStorage 同步到任何其他綁定實例中,如 PersistentStorage 或其他綁定的UI組件。 @StorageLink 狀態數據具有以下特征:

  • 支持多種數據類型:支持的數據類型和 @State 一致且支持 object 。
  • 需要本地初始化:必須為所有 @StorageLink 變量分配初始值。
  • 數據狀態全局化:使用 @StorageLink 修飾的數據變化后全局都會改變。
  • 數據持久化:通過搭配 PersistentStorage 接口實現數據持久化。
    • 綁定數據
      簡單樣例如下所示:
      @Entry @Component struct ComponentTest {
      
        @StorageLink('time') time: string = "1648643734154";// 使用StorageLink標記并初始化
      
        build() {
          Column({space: 10}) {
      
            Text(`父組件【${this.time}】`) // 使用time值
              .fontSize(20)
              .backgroundColor(Color.Pink)
      
            Button('更新時間')
              .onClick(() = > {
                this.time = new Date().getTime().toString();// 更改time的值
              })
          }
          .width('100%')
          .height('100%')
          .padding(10)
        }
      }
      

運行結果如下圖所示:

2_5_4_1

-   **雙向綁定數據**

    簡單樣例如下所示:

    ```
    @Entry @Component struct ComponentTest {

      @StorageLink('time') time1: string = "1648643734154";
      @StorageLink('time') time2: string = "abcdefefwefwewee";

      build() {
        Column({space: 10}) {

          Text(`父組件【${this.time1}】`)
            .fontSize(20)
            .backgroundColor(Color.Pink)

          Item();
          Item();

          Button('更新時間')
            .onClick(() = > {
              this.time2 = new Date().getTime().toString();
            })
        }
        .width('100%')
        .height('100%')
        .padding(10)
      }
    }

    @Component struct Item {

      @StorageLink('time') time: string = "OpenHarmony";

      build() {
        Text(`子組件【${this.time}】`)
          .fontSize(20)
          .backgroundColor(Color.Grey)
          .onClick(() = > {
            this.time = new Date().getTime().toString();
          })
      }
    }
    ```

運行結果如下圖所示:

2_5_4_2

  • 頁面間數據綁定

簡單樣例如下圖所示:


// 第一個頁面
@Entry @Component struct ComponentTest {

  @StorageLink('time') time1: string = "1648643734154";// 應用key的值以首次初始化的值為準
  @StorageLink('time') time2: string = "abcdefefwefwewee";// time2以time1的值為準

  build() {
    Column({space: 10}) {

      Text(`父組件【${this.time1}】`)
        .fontSize(20)
        .backgroundColor(Color.Pink)

      Item();// 使用自定義組件
      Item();// 使用自定義組件

      Button('更新時間')
        .onClick(() = > {
          this.time2 = new Date().getTime().toString();// 更改time2的值,所有使用key的頁面都會刷新
        })

      Button('跨頁面數據綁定')
        .onClick(() = > {
          router.push({uri: "pages/test/setting"})// 打開第二個頁面
        })
    }
    .width('100%')
    .height('100%')
    .padding(10)
  }
}

// 自定義個組件
@Component struct Item {

  @StorageLink('time') time: string = "OpenHarmony";// time的值以key第一次出現的初始化為準

  build() {
    Text(`子組件【${this.time}】`)
      .fontSize(20)
      .backgroundColor(Color.Grey)
      .onClick(() = > {
        this.time = new Date().getTime().toString();// 更改time的值,所有使用key的頁面都會刷新
      })
  }
}


// 第二個頁面
@Entry @Component struct Setting {

  @StorageLink('time') tips: string = "我是第二個頁面"; // tips的值以'key'第一次出現的為準

  build() {
    Column({space: 10}) {
      Text(this.tips) // tips的值以'key'第一次出現的為準
        .fontSize(20)
        .margin(20)
        .onClick(() = > {
          this.tips = "0000000000000" // 更改tips的值,所有使用key的頁面都會更新
        })

      Button('返回')
        .onClick(() = > {
          router.back()// 點擊返回,首頁的數據會更改
        })
    }
    .width('100%')
    .height('100%')
  }
}

運行結果如下圖所示:

2_5_4_3

  • 持久化數據

@StorageLink 搭配 PersistentStorage 接口可以實現數據本地持久化,簡單樣例如下圖所示:


// 持久化存儲key并設置默認值
PersistentStorage.PersistProp("time", "Hello, OpenHarmony")

@Entry @Component struct ComponentTest {

  // 初始化time1,如果AppStorage
  @StorageLink('time') time1: string = "1648643734154";
  @StorageLink('time') time2: string = "OpenHarmony";

  build() {
    Column({space: 10}) {

      Text(`父組件【${this.time1}】`)
        .fontSize(20)
        .backgroundColor(Color.Pink)

      Item();
      Item();

      Button('更新時間')
        .onClick(() = > {
          this.time2 = new Date().getTime().toString();
        })

      Button('跨頁面數據綁定')
        .onClick(() = > {
          router.push({uri: "pages/test/setting"})
        })
    }
    .width('100%')
    .height('100%')
    .padding(10)
  }
}

// 自定義組件
@Component struct Item {

  @StorageLink('time') time: string = "OpenHarmony";

  build() {
    Text(`子組件【${this.time}】`)
      .fontSize(20)
      .backgroundColor(Color.Grey)
      .onClick(() = > {
        this.time = new Date().getTime().toString();
      })
  }
}

運行結果如下圖所示:

2_5_4_4

@Watch修飾符

@Watch 用來監聽狀態變量的變化,當它修飾的狀態變量發生變更時,回調相應的方式,語法結構為:

@State @Watch("function_name") count : number = 0;

上述語句表示:給狀態變量 count 增加一個 @Watch 裝飾器,通過 @Watch 注冊一個回調方法 function_name , 當狀態變量 count 被改變時, 觸發 function_name 回調。

簡單樣例如下所示:

@Entry @Component struct WatchTest {

@State @Watch("onBasketUpdated") shopBasket: Array< number > = [7, 12, 47, 3];
@State totalPurchase: number = 0;

updateTotal(): number {
let sum = 0;
this.shopBasket.forEach((i) = > {
sum += i;
});
// 計算新的購物籃總價值,如果超過100RMB,則適用折扣
this.totalPurchase = (sum < 100) ? sum : 0.9 * sum;
return this.totalPurchase;
}

onBasketUpdated(propName: string): void {
this.updateTotal();
}

build() {
Column({space: 10}) {
Text(`${this.totalPurchase}`)
.fontSize(30)

Button("add to basket")
.onClick(() = > {
this.shopBasket.push(Math.round(100 * Math.random()))
})
}
.width("100%")
.height("100%")
.padding(10)

}
}

樣例運行結果如下圖所示:

2_5_5_1

集合 shopBasket 是一個狀態變量,它被 @Watch 修飾符修飾并綁定了 onBasketUpdated() 方法回調,當點擊按鈕往 shopBasket 里添加數據時會觸發 onBasketUpdated() 方法的調用,該方法里邊執行了 totalPurchase 的數據計算,最后頁面刷新。

@Watch 裝飾器只能監聽 @State 、 @Prop 、 @Link 、 @ObjectLink 、 @Provide 、 @Consume 、 @StorageProp 以及 @StorageLink 裝飾的變量。

小結

通過對ArkUI三種狀態管理的介紹,可以根據具體的業務場景選擇不同的狀態管理模式。


審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 鴻蒙
    +關注

    關注

    55

    文章

    1769

    瀏覽量

    42153
  • HarmonyOS
    +關注

    關注

    79

    文章

    1878

    瀏覽量

    29336
  • OpenHarmony
    +關注

    關注

    23

    文章

    3381

    瀏覽量

    15194
收藏 人收藏

    評論

    相關推薦

    HarmonyOS開發實例:【分布式數據管理

    eTS中分布式數據管理的使用,包括KVManager對象實例的創建和KVStore數據流轉的使用。
    的頭像 發表于 04-11 09:57 ?489次閱讀
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>開發</b><b class='flag-5'>實例</b>:【分布式數據<b class='flag-5'>管理</b>】

    HarmonyOS開發必備知識

    這篇文檔帶領大家掌握HarmonyOS開發的一些必備基礎知識:1、應用基礎知識;2、應用配置文件;3、資源文件;4、應用數據管理;5、應用權限管理注:文檔和視頻中所有的圖片及代碼截圖皆
    發表于 09-10 17:39

    HarmonyOS應用開發學習路線

    “面向未來”的操作系統到底是什么、能帶來什么、有什么特征,看這里:HarmonyOS 概述2.了解HarmonyOS應用開發基礎知識HarmonyOS的應用結構、配置文件、資源文件、數
    發表于 09-11 16:14

    HarmonyOS應用開發NFC、藍牙、WLAN、網絡管理、電話服務資料

    和其他設備互聯互通。HarmonyOS網絡管理模塊主要提供以下功能:數據連接管理:網卡綁定,打開URL,數據鏈路參數查詢。數據網絡管理:指定數據網絡傳輸,獲取數據網絡
    發表于 09-21 14:19

    HarmonyOS】應用開發文檔

    /basic-fundamentals-0000000000041611快速入門補充該實例在新建工程時需要選擇的設備類型和模板,避免開發者選擇錯誤https://developer.harmonyos.com/cn/docs/d
    發表于 10-14 18:04

    絕對干貨!HarmonyOS開發者日資料全公開,鴻蒙開發者都在看

    應用開發模板,分布式調試調優,上架開發規范解讀等。6、HarmonyOS 分布式應用框架深入解讀:該主題深度解析HarmonyOS分布式應用框架,包括系統架構分層,遷移、協同框架及分布
    發表于 08-04 14:36

    【資料】華為HarmonyOS 音頻開發管理指南

    華為HarmonyOS 音頻開發管理指南回復帖子查看資料下載鏈接:[hide][/hide]
    發表于 08-12 12:08

    HarmonyOS卡片開發--服務卡片概述

    片服務。 卡片提供方實例管理模塊:由卡片提供方開發者實現,負責對卡片管理服務分配的卡片實例進行持久化管理
    發表于 09-22 14:10

    【資料合集】HarmonyOS應用開發的學習路線

    HarmonyOS應用開發基礎知識  HarmonyOS的應用結構、配置文件、資源文件、數據管理、權限隱私管理等應用
    發表于 03-14 14:02

    HarmonyOS/OpenHarmony應用開發-FA模型綜述

    FA模型整體架構****HarmonyOS用戶程序的開發本質上就是開發Ability。HarmonyOS系統是通過對Ability調度,結合系統提供的一致性調度契約對Ability進行
    發表于 12-07 10:39

    HarmonyOS/OpenHarmony應用開發-PageAbility開發體驗

    功能簡介PageAbility是具備ArkUI實現的Ability,是開發者具體可見并可以交互的Ability實例。開發者通過IDE創建Ability時,IDE會自動創建相關模板代碼
    發表于 12-08 11:03

    HarmonyOS后臺任務管理開發指南上線!

    HarmonyOS 后臺任務管理開發指南上新內容,希望能夠幫助開發者更高效地探索、體驗、上手 HarmonyOS。 同時,我們十分重視
    發表于 11-29 09:58

    華為開發HarmonyOS零基礎入門:聲明式UI開發

    華為開發HarmonyOS零基礎入門:聲明式UI開發,用戶界面任何狀態的改變都只有一種編碼途徑,完善一些交互體驗。
    的頭像 發表于 10-23 09:55 ?1159次閱讀
    華為<b class='flag-5'>開發</b>者<b class='flag-5'>HarmonyOS</b>零基礎入門:聲明式UI<b class='flag-5'>開發</b>

    HarmonyOS開發:舒爾特方格游戲

    為豐富 HarmonyOS 對云端開發的支持、實現 HarmonyOS 生態端云聯動,DevEco Studio 推出了云開發功能,開發者在
    的頭像 發表于 06-19 15:05 ?525次閱讀
    <b class='flag-5'>HarmonyOS</b>云<b class='flag-5'>開發</b>:舒爾特方格游戲

    開發者說】HarmonyOS實踐之應用狀態變量共享

    】,即可獲得投稿渠道。期待你們的分享~ 平時在開發的過程中,我們會在應用中共享數據,在不同的頁面間共享信息。雖然常用的共享信息,也可以通過不同頁面中組件間信息共享的方式,但有時使用應用級別的狀態管理會讓
    的頭像 發表于 12-26 21:20 ?431次閱讀
    【<b class='flag-5'>開發</b>者說】<b class='flag-5'>HarmonyOS</b>實踐之應用<b class='flag-5'>狀態</b>變量共享
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>