HarmonyOS开发之全局状态管理

锦通  论坛元老 | 2024-9-16 17:32:38 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1021|帖子 1021|积分 3063

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x

前言

一般的路由传参,得当父传子,单向或者双向绑定,但是一个状态被多个模块使用,组件没有关系的情况下就必要使用到全局状态管理。

一、LocalStorage:页面级UI状态存储



  • 通过@Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage支持UIAbility实例内多个页面间状态共享。
  • 装饰器:@LocalStorageProp和@LocalStorageLink。
1.@LocalStorageProp单向同步(只改变当前的值,不会同步到LoacalSorage中去)

  1. //父组件
  2. // 创建新实例并使用给定对象初始化
  3. let para: Record<string, number> = {PropA:20};
  4. let storage: LocalStorage = new LocalStorage(para);
  5. import Son from '../components/son'
  6. // 將storage 進行註冊
  7. @Entry(storage)
  8. @Component
  9. struct Index {
  10.   // 将本地存储中 propA赋值给 storageProp1  =1是storageProp1取不到值时的默认值
  11.   //单向赋值 结果不会同步到LocalStorage
  12.    @LocalStorageProp('PropA') storageProp1: number= 1;
  13.   build() {
  14.     Row() {
  15.       Column() {
  16.         //儿子组件
  17.         Son()
  18.         Button(`Parent from LocalStorage ${this.propA}`)
  19.           .onClick(()=>{
  20.           //点击propA+1 只改变当前页面的值 而不改变localStorage
  21.             this.propA+=1
  22.           })
  23.       }
  24.       .width('100%')
  25.     }
  26.     .height('100%')
  27.   }
  28. }
  29. //子组件  在根组件定义的 下面的子组件 能是使用这个实例
  30. import Sun from './sun'
  31. @Component
  32. export default struct Son {
  33. // 单向绑定
  34.   @LocalStorageProp('PropA') storageProp2: number = 2;
  35.   build() {
  36.     Column() {
  37.       // @ts-ignore
  38.       Text(`Parent from LocalStorage ${this.storageProp2}`)
  39.       Sun()
  40.   }
  41.   }
  42. }
复制代码
2.@LocalStorageLink双向同步(改变当前的值,同步到LoacalSorage)

  1. //父组件
  2. // 创建新实例并使用给定对象初始化
  3. let para: Record<string, number> = {PropA:20};
  4. let storage: LocalStorage = new LocalStorage(para);
  5. import Son from '../components/son'
  6. // 將storage 進行註冊
  7. @Entry(storage)
  8. @Component
  9. struct Index {
  10.   // 将本地存储中 propA赋值给 storageProp1  =1是storageProp1取不到值时的默认值
  11.   //双向赋值 结果同步到LocalStorage
  12.   @LocalStorageLink('PropA') storageLink: number = 1;
  13.   build() {
  14.     Row() {
  15.       Column() {
  16.         //儿子组件
  17.         Son()
  18.         Button(`Parent from LocalStorage ${this.propA}`)
  19.           .onClick(()=>{
  20.           //点击propA+1 只改变当前页面的值 而不改变localStorage
  21.             this.propA+=1
  22.           })
  23.       }
  24.       .width('100%')
  25.     }
  26.     .height('100%')
  27.   }
  28. }
  29. //子组件  在根组件定义的 下面的子组件 能是使用这个实例
  30. import Sun from './sun'
  31. @Component
  32. export default struct Son {
  33. // 双向绑定 不管哪个组件改变了localStorage的值,这里的值都会同步改变
  34.   @LocalStorageLink('PropA') storageProp2: number = 2;
  35.   build() {
  36.     Column() {
  37.       // @ts-ignore
  38.       Text(`Parent from LocalStorage ${this.storageProp2}`)
  39.       Sun()
  40.   }
  41.   }
  42. }
复制代码
3.将LocalStorage实例从UIAbility共享到一个或多个视图



  • 状态被任意组件或者页面使用
  • 可以使用@LocalStorageProp单向绑定,也可以使用@LocalStorageLink 双向绑定更新loaclStorage
  1. //EntrySbility.js
  2. export default class EntryAbility extends UIAbility {
  3.   //UIAbility状态共享到一个或多个视图
  4.   //在初始化定义状态变量
  5.   para:Record<string, number> = { 'PropA': 47 };
  6.   storage: LocalStorage = new LocalStorage(this.para);
  7.   onWindowStageCreate(windowStage: window.WindowStage) {
  8.     hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
  9.         //在窗口 将storage暴露出去
  10.     windowStage.loadContent('pages/Index', this.storage, (err, data) => {
  11.       if (err.code) {
  12.         hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
  13.         return;
  14.       }
  15.       hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
  16.     });
  17.   }
  18. }
复制代码
  1. //pages/index.ets
  2. // 通过getShared接口获取EntrySbility暴露出的stage共享的LocalStorage实例
  3. let storage = LocalStorage.GetShared()
  4. import Son from '../components/son'
  5. // 將storage 進行註冊
  6. //不管是在根组件祖册的LocalStorage ,还是在EntrySbility注册的
  7. //@Entry(storage) 注册了 那么这个组件以及下面的子组件都可以直接使用
  8. //反之,就需要重新引入或者创建LocalStorage
  9. @Entry(storage)
  10. @Component
  11. struct Index {
  12.   //这块就可以根据业务逻辑 去使用不同的方法
  13.   
  14.   //单向赋值 结果不会同步到LocalStorage
  15.   // @LocalStorageProp('PropA') storageProp1: number= 1;
  16.   //双向赋值 结果同步到LocalStorage
  17.   // @LocalStorageLink('PropA') storageProp1: number = 1;
  18.   @LocalStorageLink('PropA') propA: number = 1;
  19.   build() {
  20.     Row() {
  21.       Column() {
  22.         //儿子组件
  23.         Son()
  24.         Button(`Parent from LocalStorage ${this.propA}`)
  25.           .onClick(()=>{
  26.             this.propA+=1
  27.           })
  28.       }
  29.       .width('100%')
  30.     }
  31.     .height('100%')
  32.   }
  33. }
复制代码
二、AppStorage/PersistentStorage:应用全局的UI状态存储 / 持久化存储



  • 和AppStorage差别的是,LocalStorage是页面级的,通常应用于页面内的数据共享。而AppStorage是应用级的全局状态共享,还相称于整个应用的“中枢”,持久化数据PersistentStorage环境变量Environment都是通过AppStorage中转,才可以和UI交互。
  • 相干的装饰器:@StorageProp和@StorageLink
  • AppStorage可以和UI组件同步,且可以在应用业务逻辑中被访问。
  • AppStorage支持应用的主线程内多个UIAbility实例间的状态共享
  • AppStorage 和 PersistentStorage 在页面中可以单独定义,也可以一起使用,但是一起使用时必要做判定 ,PersistentStorage 存储的值,会被AppStorage 覆盖
  • PersistentStorage 本身 也是通过访问 AppStorage 存储数据。
1.AppStorage

  1. //pages/inde.ets
  2. AppStorage.SetOrCreate('count', 10);
  3. import Son from '../components/son'
  4. @Entry
  5. @Component
  6. struct Index {
  7.   //StorageProp 单向绑定数据 不会改变appStorage的值
  8.   // 可以通过  AppStorage.Set('count', 30); 改变appStorage值
  9.   // @StorageProp('count') appValue: number = 0;
  10.   
  11.   //StorageLink 双向绑定 改变appStorage的值
  12.   @StorageLink('count') appValue: number =0;
  13.   build() {
  14.     Row() {
  15.       Column() {
  16.         //儿子组件
  17.         Son()
  18.         // @ts-ignore
  19.         Button(`Parent from LocalStorage ${this.appValue}`)
  20.           .onClick(()=>{
  21.             this.appValue = 40
  22.           })
  23.       }
  24.       .width('100%')
  25.     }
  26.     .height('100%')
  27.   }
  28. }
复制代码
2.PersistentStorage

  1. // 当应用退出再进来时,数据依然保存在硬盘中
  2. PersistentStorage.PersistProp('count', 10);
  3. import Son from '../components/son'
  4. @Entry
  5. @Component
  6. struct Index {
  7.   //StorageProp 单向绑定数据 不会改变appStorage的值
  8.   //可以通过  AppStorage.Set('count', 30); 改变appStorage值
  9.   // @StorageProp('count') appValue: number = 0;
  10.   
  11.   //StorageLink 双向绑定 改变appStorage的值
  12.   @StorageLink('count') appValue: number =0;
  13.   build() {
  14.     Row() {
  15.       Column() {
  16.         //儿子组件
  17.         Son()
  18.         // @ts-ignore
  19.         Button(`Parent from LocalStorage ${this.appValue}`)
  20.           .onClick(()=>{
  21.             this.appValue = 40
  22.           })
  23.       }
  24.       .width('100%')
  25.     }
  26.     .height('100%')
  27.   }
  28. }
复制代码
三、Environment:设备环境查询

   必要应用步调运行的设备的环境参数,以此来作出差别的场景判定,比如多语言,暗黑模式等,必要用到Environment设备环境查询
    设备环境到 Component的更新链:Environment --> AppStorage -->Component
也是通过AppStorage 举行单向绑定
  1. // Environment 是单向数据绑定,不可改变环境变量
  2. //languageCode 是 Environment内置参数 用来判断系统语言
  3. Environment.EnvProp('languageCode', 'en');
  4. @Entry
  5. @Component
  6. struct Index {
  7.   @StorageProp('languageCode') languageCode: string = 'en';
  8.   build() {
  9.     Row() {
  10.       Column() {
  11.         // 输出当前设备的languageCode
  12.         Text(this.languageCode=='en'?'hello':'你好')
  13.       }
  14.     }
  15.   }
  16. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

锦通

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表