news 2026/6/4 14:51:00

【HarmonyOS实战】 AppStorage:应用级全局状态共享怎么做?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【HarmonyOS实战】 AppStorage:应用级全局状态共享怎么做?

文章目录

    • 前言
    • 一、HarmonyOS 的状态管理层级
    • 二、AppStorage 的基本操作
      • 2.1 写入数据(在 EntryAbility 里)
      • 2.2 在组件中读取:@StorageProp
      • 2.3 双向同步:@StorageLink
    • 三、为什么用 AppStorage 而不是普通全局变量?
    • 四、数据流向图
    • 五、完整使用示例
    • 六、AppStorage 的注意事项
      • 6.1 Key 命名要规范
      • 6.2 值类型要一致
      • 6.3 App 重启后数据丢失
    • 七、@State vs @StorageProp 怎么选?
    • 总结

前言

上一篇我们看到,EntryAbility把状态栏高度存进了AppStorage,然后GasStationPage@StorageProp读出来。

不传参、不用全局变量,两个毫不相干的地方就完成了数据共享——这就是AppStorage的魔力。这篇文章把 HarmonyOS 的状态管理体系从头讲清楚。

项目预览

一、HarmonyOS 的状态管理层级

HarmonyOS 的状态管理分三个层级:

AppStorage(应用级) ↕ 双向同步 └─ @StorageProp / @StorageLink(页面/组件访问 AppStorage) PersistentStorage(持久化) └─ 数据写入磁盘,App 重启后保留 LocalStorage(页面级) └─ 页面内或页面树内共享,比 AppStorage 范围小
存储类型作用范围是否持久化典型用途
@State单个组件内部组件自身的 UI 状态
LocalStorage页面内部或子树同一页面的多组件共享
AppStorage整个应用(全局)否(App关闭丢失)全局配置、运行时数据
PersistentStorage整个应用是(写入磁盘)用户设置、登录状态

二、AppStorage 的基本操作

2.1 写入数据(在 EntryAbility 里)

// AppStorage.setOrCreate(key, defaultValue)// 如果 key 不存在,创建并设置值// 如果 key 已存在,更新值AppStorage.setOrCreate('bottomRectHeight',bottomRectHeight);AppStorage.setOrCreate('topRectHeight',topRectHeight);

也可以用set(只更新,key 必须已存在):

AppStorage.set('bottomRectHeight',100);

或者get读取:

letheight:number|undefined=AppStorage.get<number>('bottomRectHeight');

2.2 在组件中读取:@StorageProp

// GasStationPage.ets@Componentstruct GasStationPage{// 从 AppStorage 读取 'bottomRectHeight' 的值// 如果 AppStorage 里的值变了,这里也会自动更新@StorageProp('bottomRectHeight')bottomRectHeight:number=0;// 0 是默认值(AppStorage里还没有值时使用)@StorageProp('topRectHeight')topRectHeight:number=0;}

@StorageProp单向同步:AppStorage 变化 → 组件属性更新 → UI 刷新。但组件内部修改bottomRectHeight不会反向写回 AppStorage。

2.3 双向同步:@StorageLink

如果需要双向同步(组件修改也写回 AppStorage),用@StorageLink

@Componentstruct SomeComponent{@StorageLink('userTheme')currentTheme:string='light';// 修改这个会同步到 AppStorage}

项目里用@StorageProp而不是@StorageLink:因为安全区域高度只由系统决定,不应该被组件随意修改,单向读取更安全。

三、为什么用 AppStorage 而不是普通全局变量?

你可能会想:直接定义一个全局变量不香吗?

// 直接定义全局变量(不推荐)letglobalTopHeight:number=0;letglobalBottomHeight:number=0;

全局变量的问题:

  1. 改了变量,UI 不刷新——普通变量不是响应式的,改值后还需要手动触发 UI 更新
  2. 线程安全问题——多个地方同时修改可能出问题
  3. 没有类型保护——容易写错 key,或者类型不对

AppStorage的优势:

  1. 响应式——值变化时,@StorageProp/@StorageLink修饰的属性自动更新,UI 自动重渲
  2. 类型安全——有泛型支持,AppStorage.get<number>('key')
  3. 统一管理——所有全局状态都在一个地方

四、数据流向图

EntryAbility │ ├─ 读取状态栏高度 ├─ AppStorage.setOrCreate('topRectHeight', value) └─ AppStorage.setOrCreate('bottomRectHeight', value) │ │ (AppStorage 作为中间层) │ ├─── MainPage │ @StorageProp('topRectHeight') topRectHeight: number = 0 │ @StorageProp('bottomRectHeight') bottomRectHeight: number = 0 │ └─── GasStationPage @StorageProp('topRectHeight') topRectHeight: number = 0 @StorageProp('bottomRectHeight') bottomRectHeight: number = 0

当系统安全区域变化时(avoidAreaChange事件),EntryAbility更新AppStorage,所有用@StorageProp绑定了这个 key 的组件都会收到通知,自动刷新 UI。整个流程不需要手动传参

五、完整使用示例

假设你要在应用里共享用户选择的主题色:

// 1. 在 EntryAbility.onCreate() 里初始化onCreate(want:Want,launchParam:AbilityConstant.LaunchParam):void{AppStorage.setOrCreate('primaryColor','#007AFF');// 初始化主题色}// 2. 在页面A里读取并显示@Componentstruct PageA{@StorageProp('primaryColor')primaryColor:string='#007AFF';build(){Button('确认').backgroundColor(this.primaryColor)// 使用主题色}}// 3. 在设置页里修改(双向同步)@Componentstruct SettingsPage{@StorageLink('primaryColor')// 用 @StorageLink 才能写回primaryColor:string='#007AFF';build(){Button('切换蓝色').onClick(()=>{this.primaryColor='#007AFF';// 修改后自动同步到 AppStorage})Button('切换红色').onClick(()=>{this.primaryColor='#FF3B30';// PageA 的颜色也会自动更新})}}

六、AppStorage 的注意事项

6.1 Key 命名要规范

AppStorage 是全局的,如果不同模块用了同名的 key,会互相覆盖:

// 不好的做法——容易冲突AppStorage.setOrCreate('height',100);// 推荐——带模块前缀AppStorage.setOrCreate('window_topRectHeight',100);AppStorage.setOrCreate('window_bottomRectHeight',60);

6.2 值类型要一致

// 设置时是 numberAppStorage.setOrCreate('topRectHeight',100);// 读取时类型要匹配@StorageProp('topRectHeight')topRectHeight:number=0;// ✅ 正确// 如果类型不匹配,行为未定义@StorageProp('topRectHeight')topRectHeight:string='0';// ⚠️ 危险

6.3 App 重启后数据丢失

AppStorage的数据在内存里,App 关闭后会消失。这也是为什么每次启动都要重新获取安全区域高度。如果需要持久化,改用PersistentStorage

// 持久化到磁盘(App重启后依然有值)PersistentStorage.persistProp('userSettings',{});

七、@State vs @StorageProp 怎么选?

场景用什么
只在当前组件用的数据@State
需要在多个页面/组件共享的数据AppStorage+@StorageProp
父子组件传数据(只读)@Prop
父子组件传数据(双向改)@Link
需要持久化的数据PersistentStorage+@StorageProp

总结

AppStorage是 HarmonyOS 的"全局响应式仓库":

  • 写入AppStorage.setOrCreate(key, value)(推荐)或AppStorage.set(key, value)
  • 读取@StorageProp('key')单向同步,@StorageLink('key')双向同步
  • 特点:响应式,值变化自动触发 UI 刷新,无需手动传参
  • 局限:App 关闭后数据消失,持久化需用PersistentStorage

下一篇讲Navigation 路由系统——从主页到地图页的页面跳转是怎么实现的。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/4 14:50:59

如何快速掌握无损视频剪辑:面向初学者的完整指南

如何快速掌握无损视频剪辑&#xff1a;面向初学者的完整指南 【免费下载链接】lossless-cut The swiss army knife of lossless video/audio editing 项目地址: https://gitcode.com/gh_mirrors/lo/lossless-cut 想要快速处理视频却担心画质损失&#xff1f;LosslessCut…

作者头像 李华
网站建设 2026/6/4 14:50:13

基于树莓派构建家庭安全网关:从硬件选型到软件部署全攻略

1. 项目概述&#xff1a;为什么选择树莓派构建安全网关&#xff1f;在家庭网络环境里&#xff0c;我们最常听到的抱怨是什么&#xff1f;手机电脑越来越慢&#xff0c;弹窗广告层出不穷&#xff0c;孩子不小心点进了不该看的网站&#xff0c;或者更糟——某天突然发现文件被加密…

作者头像 李华
网站建设 2026/6/4 14:47:52

基于Arduino的时序模式识别门锁:从压电传感到继电器驱动的DIY实践

1. 项目概述&#xff1a;用敲门声当钥匙&#xff0c;打造你的专属秘密门锁在智能家居和DIY安防领域&#xff0c;我们总在寻找一种平衡&#xff1a;既要足够安全&#xff0c;又要足够酷&#xff0c;最好还不用带钥匙。今天分享的这个项目&#xff0c;就完美地踩中了这几个点——…

作者头像 李华
网站建设 2026/6/4 14:44:57

快速掌握Layerdivider:AI智能图像分层终极指南

快速掌握Layerdivider&#xff1a;AI智能图像分层终极指南 【免费下载链接】layerdivider A tool to divide a single illustration into a layered structure. 项目地址: https://gitcode.com/gh_mirrors/la/layerdivider Layerdivider是一款革命性的AI图像分层工具&am…

作者头像 李华
网站建设 2026/6/4 14:42:45

基于Arduino的智能酒杯:用传感器与算法实现饮酒安全监测

1. 项目概述与核心思路几年前&#xff0c;我在一个朋友聚会上&#xff0c;亲眼目睹了一位平时酒量不错的哥们&#xff0c;因为对自己状态的误判&#xff0c;差点出了事。这件事让我思考了很久&#xff0c;我们总说“喝酒不开车”&#xff0c;但到底喝多少才算“喝了”&#xff…

作者头像 李华