本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

一、LocalStorage 概述

LocalStorage 是 ArkTS 为构建页面级别状态变量提供存储的内存内“数据库”。它主要用于页面内或 UIAbility 实例内多个页面间的 UI 状态共享。

  • 作用:提供页面级 UI 状态存储 。
  • 特性:存储在内存中,应用程序可以创建多个 LocalStorage 实例。这些实例可以在页面内共享,也可以通过 getSharedLocalStorage 接口实现跨页面、UIAbility 实例内共享 。
  • 生命周期:由应用程序决定。当应用释放最后一个指向 LocalStorage 的引用时(例如销毁最后一个使用它的自定义组件),LocalStorage 会被 JS Engine 垃圾回收 。
  • 与装饰器的关系:LocalStorage 通过与 @Component 装饰的组件不同的同步类型,提供了两个装饰器: 
    • @LocalStorageProp:与 LocalStorage 中给定属性建立单向同步关系。
    • @LocalStorageLink:与 LocalStorage 中给定属性建立双向同步关系。

二、LocalStorage 的使用

1. 创建与初始化

创建一个 LocalStorage 实例,并使用一个对象(键值对形式)进行初始化:

// 准备共享数据
const data: Record<string, string> = {
  'uname': '张三',
  'age': '18'
};
// 创建LocalStorage实例
const storage = new LocalStorage(data);

2. 与组件关联

组件树的根节点(即被 @Entry 装饰的 @Component)可以被分配一个 LocalStorage 实例。此组件的所有子组件实例将自动获得对该 LocalStorage 实例的访问权限。

@Entry(storage) // 将storage实例与根组件关联
@Component
struct TestLocalStorage03 {
  // 组件内使用LocalStorage
}

未被 @Entry 装饰的组件不会被独立分配 LocalStorage 实例,只能接受父组件通过 @Entry 传递来的 LocalStorage 实例。

3. 装饰器使用规则

@LocalStorageProp (单向同步)
项目 说明
装饰器参数 key:常量字符串,必填(字符串需要有引号)。
允许装饰的变量类型 Object、class、string、number、boolean、enum 类型,以及这些类型的数组。API version 12 及以上支持 Map、Set、Date、undefined 和 null 类型。
同步类型 单向同步:从 LocalStorage 的对应属性到组件的状态变量。组件本地的修改是允许的,但 LocalStorage 中给定的属性一旦发生变化,将覆盖本地的修改 。
被装饰变量的初始值 必须指定。如果 LocalStorage 实例中不存在属性,则作为初始化默认值,并存入 LocalStorage 中。
  • 特点
    • 允许本地修改,但本地修改不会同步回 LocalStorage 中
    • 如果 LocalStorage 中 key 对应的属性值改变(如通过 .set 接口修改),会同步给 @LocalStorageProp 并覆盖本地值 。
    • 不支持装饰Function类型。
  • 示例
    @Entry(storage)
    @Component
    struct CompA {
      @LocalStorageProp('uname') storageProp1: string = 'defaultName'; // 单向同步

      build() {
        Column() {
          Text(`Parent from LocalStorage: ${this.storageProp1}`)
          Button('Change locally')
            .onClick(() => {
              this.storageProp1 = 'LocalChange'; // 仅本地变化,不会同步回storage
            })
        }
      }
    }
@LocalStorageLink (双向同步)
项目 说明
装饰器参数 key:常量字符串,必填(字符串需要有引号)。
允许装饰的变量类型 Object、class、string、number、boolean、enum 类型,以及这些类型的数组。API version 12 及以上支持 Map、Set、Date、undefined 和 null 类型。
同步类型 双向同步:任何一方的修改都会同步到另一方。
  • 特点
    • 与 @LocalStorageProp 类似,但建立的是双向同步关系。
    • 本地修改会同步回 LocalStorage,LocalStorage 中对应属性的修改也会同步到所有绑定该属性的 @LocalStorageLink 变量。
    • 不支持装饰Function类型。
  • 示例
    @Entry(storage)
    @Component
    struct CompA {
      @LocalStorageLink('uname') storageLink1: string = 'defaultName'; // 双向同步

      build() {
        Column() {
          Text(`Parent from LocalStorage: ${this.storageLink1}`)
          Button('Change and sync to LocalStorage')
            .onClick(() => {
              this.storageLink1 = 'NewName'; // 本地变化会同步回storage
            })
        }
      }
    }

    @Component
    struct Child {
      @LocalStorageLink('uname') storageLink2: string = 'defaultName'; // 双向同步

      build() {
        Column() {
          Text(`Child from LocalStorage: ${this.storageLink2}`) // 会随Parent的修改或storage的修改而改变
        }
      }
    }

4. 在 UIAbility 中共享给多个页面

在 UIAbility 的 onWindowStageCreate 生命周期中,可以将 LocalStorage 实例传递给多个页面,实现 UIAbility 内多个页面间的状态共享:

export default class EntryAbility extends UIAbility {
  storage: LocalStorage = new LocalStorage({
    'abilitycount': 1
  });

  onWindowStageCreate(windowStage: window.WindowStage): void {
    // 将storage传递给页面'pages/Index'
    windowStage.loadContent('pages/Index', this.storage, (err, data) => {
      if (err.code) {
        // 错误处理
        return;
      }
    });
  }
}

在页面中,可以通过 LocalStorage.getSharedLocalStorage() 方法获取在 UIAbility 中共享的 LocalStorage 实例。

三、注意事项

  1. 命名属性的类型不可更改:LocalStorage 创建后,命名属性的类型就确定了。后续调用 set 方法时必须使用相同类型的值 。
  2. getShared 接口的限制:getSharedLocalStorage 接口仅能获取当前 Stage 通过 windowStage.loadContent 传入的 LocalStorage 实例,否则返回 undefined 。
  3. 初始值是必须的:使用 @LocalStorageProp 或 @LocalStorageLink 装饰变量时,必须指定初始值。如果 LocalStorage 实例中不存在对应的属性,将使用这个初始值,并会将其存入 LocalStorage 中 。
     
  4. 页面级存储:LocalStorage 是页面级存储,其生命周期与页面相关联。对于需要持久化的数据(如用户登录 token、应用配置等),应考虑使用 PersistentStorage 或其他持久化方案 。
  5. 多组件共享:一个 LocalStorage 实例在组件树上可以被分配给多个组件 。

四、使用场景

  1. 页面内组件间状态共享:例如,一个页面中多个组件需要响应同一个状态的变化 。
  2. UIAbility 内多个页面间状态共享:例如,在一个 UIAbility 内跳转的不同页面需要共享某些 UI 状态 。
     
  3. 与服务卡片的数据更新:通过 LocalStorage 可以更新服务卡片中显示的数据 。

五、@LocalStorageProp 与 @LocalStorageLink 对比

特性 @LocalStorageProp @LocalStorageLink
同步方式 单向同步 (LocalStorage -> 组件) 双向同步
本地修改是否同步回 LocalStorage
是否需要初始值
适用场景 仅需接收 LocalStorage 变化,本地修改不需同步回去 需要与 LocalStorage 保持双向数据一致

六、总结

LocalStorage 是鸿蒙应用开发中用于管理页面级UI状态的重要工具,它提供了一种在内存中存储和共享数据的机制,特别适用于组件间同一UIAbility内页面间的状态同步。

选择 @LocalStorageProp 还是 @LocalStorageLink,取决于数据流需求:是简单的接收更新,还是需要双向的交互。同时,务必注意其生命周期是页面级的,对于需要持久化的数据,应选择 PersistentStorage 等其他方案。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐