鸿蒙应用开发:AppStorage 全局状态存储用法教程

这是一个使用鸿蒙技术开发的本地原生记账应用,非常适合大家用来练手。相关源码已上传至 Github,点击此处查看项目。欢迎大家交流、指正,也欢迎提交 PR。

一、引言

在鸿蒙应用开发中,跨页面、跨组件的数据共享是一个常见需求。

想象一下,用户登录后,他的用户名需要在个人中心、订单页面、消息列表等多个地方展示。如果不使用全局状态管理,你需要把用户名一层层通过路由参数、函数参数等方式传递下去(即"Prop Drilling"),代码会变得非常冗长且难以维护。AppStorage 就是为了解决这类问题而生的,它让你的组件可以随时"连接"到一个全局的数据仓库,直接读写,无需繁琐的中间传递。

AppStorage------一个应用级别的全局 UI 状态存储中心,由 UI 框架在应用启动时自动创建。它的核心作用是让不同页面、不同组件之间能够方便地共享和响应式更新数据。

二、基本用法

2.1 初始化与设置

使用 AppStorage.setOrCreate(key, value) 在应用启动时(如 UIAbility 的 onCreate 中)初始化一个全局状态。如果该 key 已存在,则不会覆盖;如果不存在,则创建。

typescript 复制代码
onCreate(want, launchParam) {
  // 设置一个全局的登录状态,默认为 false
  AppStorage.setOrCreate('isLoggedIn', false);
  // 设置用户信息
  AppStorage.setOrCreate('userName', '未登录用户');
}

2.2 绑定到组件

AppStorage 提供了两种装饰器来将组件变量与全局状态绑定:

  • @StorageProp(key) :将组件变量与 AppStorage 中的属性进行单向绑定 。组件内部修改该变量不会同步回 AppStorage,适合只读场景。
  • @StorageLink(key) :实现双向绑定 。组件内部修改该变量会自动同步回 AppStorage,并触发所有绑定该属性的组件更新。
typescript 复制代码
@Entry
@Component
struct MyComponent {
  // 单向绑定:组件内修改不会影响全局
  @StorageProp('appTheme') theme: string = 'light';
  // 双向绑定:组件内修改会同步到全局
  @StorageLink('isLoggedIn') isLoggedIn: boolean = false;
}

2.3 外部修改

在组件外部(如非 UI 层的服务、工具类中),可以通过 AppStorage.set(key, value) 直接修改状态,所有绑定了该状态的组件会自动刷新。

typescript 复制代码
// 在任意位置修改全局状态
AppStorage.set('isLoggedIn', true);
AppStorage.set('userName', '张三');

三、示例:管理用户登录状态

以下示例展示了如何使用 AppStorage 和 @StorageLink 实现一个全局的登录状态管理,实现跨页面的状态同步。

3.1 在应用入口初始化全局状态

typescript 复制代码
// 1. 在应用入口(如 UIAbility)中初始化全局状态

// 应用启动时,设置一个全局的登录状态,默认为 false
AppStorage.setOrCreate('isLoggedIn', false);

3.2 登录页面组件

typescript 复制代码
// 2. 在页面组件中使用 @StorageLink 进行双向绑定
import { router } from '@kit.ArkUI';

@Entry
@Component
struct LoginPage {
  // 双向绑定 AppStorage 中的 'isLoggedIn' 属性
  @StorageLink('isLoggedIn') isLoggedIn: boolean = false;

  build() {
    Column({space: 20}) {
      Text(`当前登录状态: ${this.isLoggedIn ? '已登录' : '未登录'}`)
        .fontSize(20)
      if (this.isLoggedIn) {
        // 已登录状态
        Button('退出登录')
          .width("80%")
          .onClick(() => {
            // 修改 @StorageLink 变量,会自动同步到 AppStorage
            this.isLoggedIn = false;
          })
      } else {
        Button('登录')
          .width("80%")
          .onClick(() => {
            // 修改 @StorageLink 变量,会自动同步到 AppStorage
            this.isLoggedIn = true;
            router.push({
              url: "pages/ProfilePage"
            })
          })

        Button("个人中心")
          .width("80%")
          .onClick(() => {
            router.push({
              url: "pages/ProfilePage"
            })
          })
      }
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

3.3 个人中心页面组件

typescript 复制代码
// 3. 在另一个页面中,也可以直接读取同一个全局状态
@Entry
@Component
struct ProfilePage {
  // 同样绑定 'isLoggedIn' 属性
  @StorageLink('isLoggedIn') isLoggedIn: boolean = false;

  build() {
    Column() {
      Text(`当前登录状态: ${this.isLoggedIn ? '已登录' : '未登录'}`)
        .fontSize(20)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

在这个例子中,当用户在 LoginPage 点击"登录"按钮后,isLoggedIn 变为 true。这个变化会立即同步到 AppStorage,并自动通知所有绑定了 @StorageLink('isLoggedIn') 的组件(如 ProfilePage)进行重新渲染,从而实现了跨页面的状态同步。

运行效果:

四、进阶用法与注意事项

4.1 删除状态

使用 AppStorage.delete(key) 可以删除某个全局状态。

typescript 复制代码
AppStorage.delete('userName');

只要通过 @StorageProp 或 @StorageLink 引用了某个键,该键就无法被 delete 方法删除。这是为了防止因数据源被意外删除而导致 UI 显示异常。此时可以通过 AppStorage.set 更新其值。

4.2 清空与获取所有键

使用 AppStorage.clear() 可以清空 AppStorage 中的所有状态,此操作不可逆,请谨慎使用。

typescript 复制代码
// 清空所有全局状态
AppStorage.clear();

使用 AppStorage.keys() 可以获取当前 AppStorage 中所有已存储的键名,返回一个字符串数组,便于调试或遍历处理。

typescript 复制代码
// 获取所有键名
const allKeys: string[] = AppStorage.keys();
console.info('当前 AppStorage 中的键:', JSON.stringify(allKeys));

4.3 注意事项

  • 应用生命周期 :AppStorage 在应用启动时创建,应用退出时销毁,适合存储应用级别的全局状态。
  • 数据类型 :支持基本类型(number、string、boolean)以及 Object、Array 等复杂类型,但复杂类型的修改需要替换整个对象才能触发响应式更新。
  • 性能考虑 :不要将大量数据或频繁变化的数据全部放入 AppStorage,建议只存储跨页面共享的关键状态。
  • 与 LocalStorage 的区别 :AppStorage 是应用级全局单例,而 LocalStorage 是页面级共享存储,作用范围不同。

五、总结

AppStorage 是鸿蒙 ArkTS 中非常实用的全局状态管理工具,通过 @StorageProp 和 @StorageLink 装饰器,可以轻松实现跨页面、跨组件的数据共享与响应式更新。合理使用 AppStorage 能够显著简化应用状态管理逻辑,提升开发效率。

相关推荐
brien941 分钟前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance1 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M1 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写1 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李1 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易1 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
风骏时光牛马2 小时前
前沿视界
前端
kyriewen2 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员
陈随易2 小时前
3000 万人在用的翻译插件,重写一遍就是一门生意
前端·后端·程序员
IT_陈寒2 小时前
Vue的这个响应式陷阱,差点让我加班到天亮
前端·人工智能·后端