HarmonyOS第七章:应用状态共享(PersistentStorage、LocalStorage、AppStorage)

🎉 博客主页:【剑九_六千里-优快云博客】【剑九_六千里-掘金社区
🎨 上一篇文章:【HarmonyOS第六章:组件状态共享(父子组件传参、多层级组件传参、@Watch监听状态变化、@Observed与@ObjectLink、多层嵌套数据更新)
🎠 系列专栏:【HarmonyOS系列
💖 感谢大家点赞👍收藏⭐评论✍

在这里插入图片描述

在这里插入图片描述

1. PersistentStorage

PersistentStorage 允许将选定的 AppStorage 属性保留在设备磁盘上,以便在应用程序关闭后仍然保持持久化。以下是关于PersistentStorage 的一些细节和注意事项:

  • UI 和业务逻辑不应直接访问 PersistentStorage 中的属性,所有属性访问都应通过 AppStorage 进行。任何在 AppStorage 中的更改都会自动同步到 PersistentStorage
  • PersistentStorage 支持存储简单类型数据,如数字(number)、字符串(string)、布尔(boolean)、枚举(enum)等。
  • 如果需要存储对象类型的数据,可以将其转换为 JSON 字符串后再存储。
  • 注意,持久化变量最好是小于2KB的数据。如果开发者需要存储大量的数据,建议使用数据库API来进行管理和存储。

1.1. 简单数据类型的持久化,获取和修改

1.1.1. 语法

// 1. 通过 PersistentStorage.persistProp() 定义要存储的数据
// 参数一:存储的属性;参数二:存储的值
PersistentStorage.persistProp("xxx", xxx)

// 2. 通过 @StorageProp() 或 @StorageLink() 接收数据
@StorageProp("xxx")
@StorageLink("xxx")

// 3. 接收数据
xxx: number = 0;

// 4. 通过 this.xxx 使用数据
this.xxx 

1.1.2. 使用示例

在这里插入图片描述

使用 PersistentStorage 存储数据,使用 @StorageLink@StorageLink 接收数据,同时数据支持修改:

// PersistentStorage 写入磁盘-app关闭数据依然存在,持久化存储
// 存储简单数据类型:number string boolean等等
// 存储负载数据类型:array object function
PersistentStorage.PersistProp("num",100)

@Entry
@Component
struct Index {
   
   
  @StorageLink("num") // 获取数据,单向数据流,只是组件内可以改变数据,并不会写入 PersistentStorage
  // @StorageLink("num") // 获取数据,双向数据流,本地修改会同步写入到 PersistentStorage
  num:number=0 // 如果未存储,默认初始值
   build() {
   
   
    Column({
   
   space:10}) {
   
   
      Text(`${
     
     this.num}`)
      Button("修改age").onClick(()=>{
   
   
        this.num++
      })
    }.width('100%')
    .height('100%')
  }
}

1.2. 复杂数据类型的持久化,获取和修改

1.2.1. 基本使用

在这里插入图片描述

  • 注意:存储复杂类型数据时,value 必须是json
// 注意:存储复杂类型数据时,value 必须是json
PersistentStorage.persistProp("user", JSON.stringify({
   
   name: "张三", age: 18}))
interface User {
   
   
  name: string;
  age: number;
}

@Entry
@Component
struct Index {
   
   
  @StorageLink("user") // 获取数据 @StorageLink("user") 或 @StorageProp("user")
  userInfo: string = "{}" // 默认值
  @State user: User = JSON.parse(this.userInfo); // 将接收到的json转成object

  build() {
   
   
    Column() {
   
   
      Text(`${
     
     this.user.name}--${
     
     this.user.age}`) // 使用传入的数据
      Button("修改Age")
        .onClick(() => {
   
   
          this.user.age++;
        })
    }
      .width("100%")
      .height("100%")
  }
}

1.2.2. 使用 AppStorage.get() 获取数据,AppStorage.set()写入数据

这个例子中使用 @StorageLink("user") 获取数据,可以实现需求,同时我们也可以使用 AppStorage.get() 来获取数据:
在这里插入图片描述

// 注意:存储复杂类型数据时,value 必须是json
PersistentStorage.persistProp("user", JSON.stringify({
   
   name: "张三", age: 18}))
interface User {
   
   
  name: string;
  age: number;
}

@Entry
@Component
struct Index {
   
   
  @StorageLink("user")
  userInfo: string = "{}"
  @State user: User = JSON.parse(this.userInfo); // 将接收到的json转成object

  build() {
   
   
    Column() {
   
   
      Text(`${
     
     this.user.name}--${
     
     this.user.age}`) // 使用传入的数据
      Button("修改Age").onClick(() => {
   
   
        this.user.age++;
      })

      Button("获取user").onClick(() => {
   
   
        const res = AppStorage.get<string>("user") // 获取到的是原数据
        console.log(res)
      })
    }
      .width("100%")
      .height("100%")
  }
}

此时点击修改Age按钮,可以发现age被改变了,但 AppStorage.get() 获取到的是改变前的数据,此时可以通过 AppStorage.set() 重新设置数据 :
在这里插入图片描述

// 注意:存储复杂类型数据时,value 必须是json
PersistentStorage.persistProp("user", JSON.stringify({
   
   name: "张三", age: 18}))
interface User {
   
   
  name: string;
  age: number;
}

<think>好的,用户想了解鸿蒙系统中AppStorageLocalStorage的区别及适用场景,以及如何实现多页面间的状态共享。首先,我需要回顾之前提供的关于页面通信的信息,并结合用户现在提供的引用内容来组织回答。 用户引用的内容提到,LocalStorage是页面级的存储,可以在页面内或UIAbility内的页面间共享,而AppStorage应用级的全局存储。同时,用户还提到@StorageProp和@StorageLink的使用,以及如何在组件间同步状态。这些信息需要整合到区别和适用场景中。 首先,我需要明确两者的核心区别:作用域和生命周期。LocalStorage是页面级,AppStorage应用级。根据引用[2],选择依据是数据共享的范围,单个页面用LocalStorage,整个应用AppStorage。同时,引用[3]和[4]提到LocalStorage可以在UIAbility内的页面间共享,但AppStorage是整个应用范围。 接下来,要详细说明两者的区别,可能需要分点列出,如作用域、生命周期、数据同步方式等。然后给出适用场景,比如LocalStorage适合同一页面或同一UIAbility内的多个页面共享AppStorage适合跨UIAbility或整个应用共享。 在实现多页面状态共享的方法部分,用户已经知道EventHub、参数传递等,但这里需要重点放在AppStorageLocalStorage上,同时可以提到PersistentStorage用于持久化,以及通过UIAbility传递LocalStorage实例的方法。引用[4]中提到可以将LocalStorage实例从UIAbility共享到视图,这可能涉及到在创建页面时传入LocalStorage实例,从而在多个页面间共享同一实例。 另外,需要注意用户可能关心的数据同步机制,比如@StorageLink和@StorageProp的区别,以及如何实现双向绑定。引用[1]中的例子展示了不同组件之间如何同步状态,这可以作为使用场景的示例。 还要考虑用户的实际应用场景,比如配置设置、主题切换适合AppStorage,而复杂页面的组件间共享适合LocalStorage。同时,需要提醒用户在使用LocalStorage跨页面时,需通过UIAbility传递实例,而AppStorage直接全局可用。 最后,总结两者的区别,并给出选择建议,帮助用户根据具体需求决定使用哪种存储方案。同时,确保回答结构清晰,分点明确,便于用户理解和应用。</think>### 鸿蒙系统中 AppStorageLocalStorage 的深度解析及多页面状态共享实践 --- #### **一、核心区别与适用场景对比** | **特性** | **LocalStorage** | **AppStorage** | |------------------------|----------------------------------------------------------------------------------|--------------------------------------------------------------------------------| | **作用域** | **页面级**(通过 `@Entry` 装饰器绑定到页面或 UIAbility 内共享)[^3][^4] | **应用级**(全局单例,所有页面和 UIAbility 均可访问)[^1][^2] | | **生命周期** | 跟随绑定页面的生命周期(页面销毁则数据失效)[^3] | 与应用生命周期一致(应用退出后数据仍可通过持久化存储保留)[^1][^3] | | **数据同步机制** | 支持组件间**双向绑定**(通过 `@StorageLink`)或**单向绑定**(`@StorageProp`)[^1][^4] | 全局共享,修改后**所有绑定组件自动更新**(通过 `@StorageLink`/`@StorageProp`) | | **典型使用场景** | - 同一页面内多组件状态共享<br>- 同一 UIAbility 内多个页面共享临时数据[^3][^4] | - 全局用户配置(如主题、语言)<br>- 跨 UIAbility 的核心业务数据共享[^1][^2] | --- #### **二、多页面状态共享的实现方法** ##### **1. 使用 LocalStorage 实现页面间共享** - **适用场景**:同一 UIAbility 内的多个页面需要共享状态(如购物车商品列表)。 - **实现步骤**: 1. **创建 LocalStorage 实例**:在 UIAbility 中初始化并传递到页面。 ```typescript // UIAbility 中创建 LocalStorage 实例 let localStorage = new LocalStorage({ cartItems: [] }); onWindowStageCreate(windowStage: Window.WindowStage) { windowStage.loadContent('pages/PageA', localStorage); // 将实例传递给页面 } ``` 2. **页面间共享实例**:通过 `@Entry` 装饰器注入 LocalStorage。 ```typescript // PageA 使用 LocalStorage @Entry(localStorage) @Component struct PageA { @StorageLink('cartItems') cartItems: Array<Item> = []; // 操作 cartItems 会自动同步到 LocalStorage } // PageB 共享同一实例 @Entry(localStorage) @Component struct PageB { @StorageLink('cartItems') cartItems: Array<Item> = []; } ``` - **优势**:轻量级,数据隔离性好,适合临时状态[^3]。 ##### **2. 使用 AppStorage 实现全局共享** - **适用场景**:跨 UIAbility 或全应用共享数据(如用户登录状态)。 - **实现步骤**: 1. **存储数据**:在任意位置设置全局状态。 ```typescript AppStorage.setOrCreate('isLoggedIn', false); // 初始化登录状态 ``` 2. **组件中绑定数据**:通过装饰器自动同步。 ```typescript @Component struct UserProfile { @StorageLink('isLoggedIn') isLoggedIn: boolean = false; build() { if (this.isLoggedIn) { Text('用户已登录'); } } } ``` 3. **跨 UIAbility 同步**:不同 UIAbility 的页面均可访问同一数据。 - **优势**:数据持久化能力强,支持生命周期管理[^2]。 ##### **3. 结合 PersistentStorage 持久化存储** - **扩展场景**:需要长期保留的全局数据(如用户偏好设置)。 - **实现方式**: ```typescript // 将 AppStorage 中的数据与持久化存储绑定 PersistentStorage.persistProp('themeMode', 'light'); // 使用方式与 AppStorage 一致 AppStorage.set('themeMode', 'dark'); // 修改后自动持久化到设备 ``` --- #### **三、关键选择依据与最佳实践** 1. **作用域优先级** - **优先 LocalStorage**:若数据仅在单个复杂页面的组件间共享(如表单多步骤填写),避免污染全局状态[^4]。 - **必选 AppStorage**:若数据需跨多个 UIAbility(如从主页跳转到独立设置页),或需要持久化[^2][^3]。 2. **性能优化建议** - **LocalStorage**:页面销毁时主动清除无用数据,减少内存占用。 - **AppStorage**:对高频更新数据使用 `@StorageLink` 双向绑定,低频数据使用 `@StorageProp` 避免不必要的渲染[^1]。 3. **数据安全** - **敏感数据**(如 Token):优先使用 `AppStorage` + 加密存储,避免通过 URL 参数传递[^3]。 --- #### **四、总结** | **场景** | **推荐方案** | **示例** | |------------------------------|-----------------------|---------------------------------------| | 页面内多组件状态同步 | LocalStorage | 表单控件的联动状态 | | 同一 UIAbility 内多页面共享 | LocalStorage 实例传递 | 电商应用的购物车流程 | | 跨 UIAbility 或全局配置 | AppStorage | 用户身份认证状态、主题模式 | | 需要持久化的全局数据 | AppStorage + PersistentStorage | 用户个人资料、应用设置 | --- **相关问题**: 1. 如何通过 `@StorageLink` 和 `@StorageProp` 实现父子组件的双向数据绑定? 2. 在多线程场景下,AppStorage 的数据访问是否需要同步控制? 3. 如何监控 LocalStorage 中特定数据的变化并触发自定义逻辑?
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

剑九_六千里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值