HarmonyOS开发之全局状态管理

文章目录


前言

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


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

  • 通过@Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage支持UIAbility实例内多个页面间状态共享。
  • 装饰器:@LocalStorageProp和@LocalStorageLink。

1.@LocalStorageProp单向同步(只改变当前的值,不会同步到LoacalSorage中去)

cpp 复制代码
//父组件
// 创建新实例并使用给定对象初始化
let para: Record<string, number> = {PropA:20};
let storage: LocalStorage = new LocalStorage(para);
import Son from '../components/son'
// 將storage 進行註冊
@Entry(storage)
@Component
struct Index {
  // 将本地存储中 propA赋值给 storageProp1  =1是storageProp1取不到值时的默认值
  //单向赋值 结果不会同步到LocalStorage
   @LocalStorageProp('PropA') storageProp1: number= 1;
  build() {
    Row() {
      Column() {
        //儿子组件
        Son()
        Button(`Parent from LocalStorage ${this.propA}`)
          .onClick(()=>{
          //点击propA+1 只改变当前页面的值 而不改变localStorage
            this.propA+=1
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}



//子组件  在根组件定义的 下面的子组件 能是使用这个实例
import Sun from './sun'
@Component
export default struct Son {
// 单向绑定
  @LocalStorageProp('PropA') storageProp2: number = 2;
  build() {
    Column() {
      // @ts-ignore
      Text(`Parent from LocalStorage ${this.storageProp2}`)
      Sun()
  }
  }
}

2.@LocalStorageLink双向同步(改变当前的值,同步到LoacalSorage)

cpp 复制代码
//父组件
// 创建新实例并使用给定对象初始化
let para: Record<string, number> = {PropA:20};
let storage: LocalStorage = new LocalStorage(para);
import Son from '../components/son'
// 將storage 進行註冊
@Entry(storage)
@Component
struct Index {
  // 将本地存储中 propA赋值给 storageProp1  =1是storageProp1取不到值时的默认值
  //双向赋值 结果同步到LocalStorage
  @LocalStorageLink('PropA') storageLink: number = 1;
  build() {
    Row() {
      Column() {
        //儿子组件
        Son()
        Button(`Parent from LocalStorage ${this.propA}`)
          .onClick(()=>{
          //点击propA+1 只改变当前页面的值 而不改变localStorage
            this.propA+=1
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}



//子组件  在根组件定义的 下面的子组件 能是使用这个实例
import Sun from './sun'
@Component
export default struct Son {
// 双向绑定 不管哪个组件改变了localStorage的值,这里的值都会同步改变
  @LocalStorageLink('PropA') storageProp2: number = 2;
  build() {
    Column() {
      // @ts-ignore
      Text(`Parent from LocalStorage ${this.storageProp2}`)
      Sun()
  }
  }
}

3.将LocalStorage实例从UIAbility共享到一个或多个视图

  • 状态被任意组件或者页面使用
  • 可以使用@LocalStorageProp单向绑定,也可以使用@LocalStorageLink 双向绑定更新loaclStorage
cpp 复制代码
//EntrySbility.js
export default class EntryAbility extends UIAbility {
  //UIAbility状态共享到一个或多个视图
  //在初始化定义状态变量
  para:Record<string, number> = { 'PropA': 47 };
  storage: LocalStorage = new LocalStorage(this.para);

  onWindowStageCreate(windowStage: window.WindowStage) {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
	//在窗口 将storage暴露出去
    windowStage.loadContent('pages/Index', this.storage, (err, data) => {
      if (err.code) {
        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
        return;
      }
      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
    });
  }
 }
cpp 复制代码
//pages/index.ets

// 通过getShared接口获取EntrySbility暴露出的stage共享的LocalStorage实例
let storage = LocalStorage.GetShared()

import Son from '../components/son'
// 將storage 進行註冊 
//不管是在根组件祖册的LocalStorage ,还是在EntrySbility注册的
//@Entry(storage) 注册了 那么这个组件以及下面的子组件都可以直接使用
//反之,就需要重新引入或者创建LocalStorage 
@Entry(storage)
@Component
struct Index {
  //这块就可以根据业务逻辑 去使用不同的方法
  
  //单向赋值 结果不会同步到LocalStorage
  // @LocalStorageProp('PropA') storageProp1: number= 1;
  //双向赋值 结果同步到LocalStorage
  // @LocalStorageLink('PropA') storageProp1: number = 1;

  @LocalStorageLink('PropA') propA: number = 1;
  build() {
    Row() {
      Column() {
        //儿子组件
        Son()
        Button(`Parent from LocalStorage ${this.propA}`)
          .onClick(()=>{
            this.propA+=1
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}

二、AppStorage/PersistentStorage:应用全局的UI状态存储 / 持久化存储

  • 和AppStorage不同的是,LocalStorage是页面级的,通常应用于页面内的数据共享。而AppStorage是应用级的全局状态共享,还相当于整个应用的"中枢",持久化数据PersistentStorage环境变量Environment都是通过AppStorage中转,才可以和UI交互。

  • 相关的装饰器:@StorageProp和@StorageLink

  • AppStorage可以和UI组件同步,且可以在应用业务逻辑中被访问。

  • AppStorage支持应用的主线程内多个UIAbility实例间的状态共享

  • AppStorage 和 PersistentStorage 在页面中可以单独定义 ,也可以一起使用 ,但是一起使用时需要做判断 ,PersistentStorage 存储的值,会被AppStorage 覆盖

  • PersistentStorage 本身 也是通过访问 AppStorage 存储数据。

1.AppStorage

cpp 复制代码
//pages/inde.ets
AppStorage.SetOrCreate('count', 10);
import Son from '../components/son'
@Entry
@Component
struct Index {
  //StorageProp 单向绑定数据 不会改变appStorage的值
  // 可以通过  AppStorage.Set('count', 30); 改变appStorage值
  // @StorageProp('count') appValue: number = 0;
  
  //StorageLink 双向绑定 改变appStorage的值
  @StorageLink('count') appValue: number =0;
  build() {
    Row() {
      Column() {
        //儿子组件
        Son()
        // @ts-ignore
        Button(`Parent from LocalStorage ${this.appValue}`)
          .onClick(()=>{
            this.appValue = 40
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}

2.PersistentStorage

cpp 复制代码
// 当应用退出再进来时,数据依然保存在硬盘中
PersistentStorage.PersistProp('count', 10);
import Son from '../components/son'
@Entry
@Component
struct Index {
  //StorageProp 单向绑定数据 不会改变appStorage的值
  //可以通过  AppStorage.Set('count', 30); 改变appStorage值
  // @StorageProp('count') appValue: number = 0;
  
  //StorageLink 双向绑定 改变appStorage的值
  @StorageLink('count') appValue: number =0;

  build() {
    Row() {
      Column() {
        //儿子组件
        Son()
        // @ts-ignore
        Button(`Parent from LocalStorage ${this.appValue}`)
          .onClick(()=>{
            this.appValue = 40
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}

三、Environment:设备环境查询

需要应用程序运行的设备的环境参数,以此来作出不同的场景判断,比如多语言,暗黑模式等,需要用到Environment设备环境查询
设备环境到 Component的更新链:Environment --> AppStorage -->Component

也是通过AppStorage 进行单向绑定

cpp 复制代码
// Environment 是单向数据绑定,不可改变环境变量
//languageCode 是 Environment内置参数 用来判断系统语言
Environment.EnvProp('languageCode', 'en');

@Entry
@Component
struct Index {
  @StorageProp('languageCode') languageCode: string = 'en';
  build() {
    Row() {
      Column() {
        // 输出当前设备的languageCode
        Text(this.languageCode=='en'?'hello':'你好')
      }
    }
  }
}
相关推荐
小镇梦想家1 小时前
鸿蒙-服务卡片
harmonyos
小彭SG1 小时前
5年前端机缘巧合做起鸿蒙开发,你也要来吗?
前端·harmonyos
机器瓦力1 小时前
Flutter应用开发:鸿蒙 HarmonyOS NEXT Beta 移植
harmonyos
西辰Knight1 小时前
【Flutter+鸿蒙】从Flutter开发者视角来看鸿蒙是怎么样的?
flutter·harmonyos
别说我什么都不会1 小时前
鸿蒙(OpenHarmony)性能优化实战-Trace
性能优化·harmonyos
电子小子洋酱2 小时前
ESP32移植Openharmony外设篇(10)inmp441麦克风
单片机·物联网·华为·harmonyos·鸿蒙
睿麒2 小时前
鸿蒙app 开发 高效的 存储 数据 推荐使用 @tencent/mmkv(V2.1.0):
华为·harmonyos
程序员的那些事_2 小时前
华为重拳出击!华为重拳出击!华为重拳出击!
华为
全栈若城3 小时前
52.HarmonyOS NEXT 登录模块开发教程(六):UI设计与用户体验优化
ui·harmonyos·ux·harmonyos next
轻口味3 小时前
【每日学点HarmonyOS Next知识】tab拦截、组件方法做参数、自定义组件链式调用、多次观察者监听、横竖屏切换
pytorch·华为·harmonyos·harmonyosnext