
鸿蒙应用开发实战【08】— AppStorage 全局状态与跨页面通信前言欢迎加入开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.net在号码助手中当用户点击应用列表中的某一项时需要把被点击项的bindingId传递给AppDetailPage。HarmonyOS 的路由参数传递router.pushUrl({ params: {...} })在子组件中存在不可靠问题因此我们使用AppStorage作为跨页面通信的主通道。本篇深入讲解 AppStorage 的原理、使用模式以及与路由参数的对比。本篇涵盖AppStorage 原理、setOrCreate / get / set、StorageProp / StorageLink 装饰器、router.getParams 的局限性、跨页面传参的完整实践。一、AppStorage 概述1.1 什么是 AppStorageAppStorage是 ArkUI 框架提供的应用级全局键值存储在整个应用生命周期内存在所有 UIAbility 和页面都可访问。特性AppStorageLocalStoragePersistentStorage作用域应用全局页面/组件应用全局持久化生命周期进程生命周期组件生命周期持久化到磁盘响应式✅✅✅持久化❌重启清空❌✅适用场景跨页面状态共享组件树内部用户偏好设置1.2 AppStorage 的核心 API// 写入如不存在则创建如已存在则更新AppStorage.setOrCreatenumber(current_binding_id,42)AppStorage.setOrCreatestring(user_theme,light)// 读取constidAppStorage.getnumber(current_binding_id)// 更新已有值AppStorage.setnumber(current_binding_id,99)// 删除AppStorage.delete(current_binding_id)// 检查是否存在constexistsAppStorage.has(current_binding_id)二、号码助手中的跨页面传参方案2.1 问题背景// AppListItem.ets — 子组件中导航到详情页// 方案1router params问题方案this.getUIContext().getRouter().pushUrl({url:pages/AppDetailPage,params:{bindingId:this.bindingId}// ⚠️ 在子组件中可能不可靠})// AppDetailPage.ets — 接收参数aboutToAppear():void{constparamsrouter.getParams()asRecordstring,number// ⚠️ params 有时为 null 或值为 0this.bindingIdparams?.[bindingId]??0}根本原因router.getParams()在子组件非Entry页面发起的导航中参数传递存在时机问题。2.2 解决方案AppStorage 双保险// AppListItem.ets — 先写入 AppStorage再导航.onClick((){if(this.bindingId0){promptAction.showToast({message:数据异常请刷新后重试})return}try{// 主通道AppStorage可靠AppStorage.setOrCreatenumber(current_binding_id,this.bindingId)// 次通道router params备用router.pushUrl({url:pages/AppDetailPage,params:{bindingId:this.bindingId}})}catch(err){promptAction.showToast({message:打开失败请重试})}})// AppDetailPage.ets — 读取 AppStorageEntryComponentstruct AppDetailPage{// 主通道StorageProp 直接绑定 AppStorageStorageProp(current_binding_id)bindingId:number0aboutToAppear():void{// 次通道router params 作为备用constparamsrouter.getParams()asRecordstring,numberif(params?.[bindingId]this.bindingId0){this.bindingIdparams[bindingId]}this.loadData()}}三、StorageProp — 单向绑定 AppStorage3.1 基本用法EntryComponentstruct AppDetailPage{// StoragePropAppStorage → 组件单向只读// current_binding_id 是 AppStorage 中的键名StorageProp(current_binding_id)bindingId:number0// ↑ 默认值AppStorage 中无此键时使用}3.2 StorageProp vs AppStorage.get 的区别特性StoragePropAppStorage.get声明位置类成员变量方法内响应式✅ 自动刷新 UI❌ 需手动读取更新时机AppStorage 变化时自动同步每次调用才读使用场景需要随 AppStorage 变化刷新 UI一次性读取// 场景需要响应 AppStorage 变化时用 StoragePropStorageProp(current_theme)theme:stringlight// theme 变化时使用它的 UI 自动刷新// 场景一次性读取用 AppStorage.getaboutToAppear():void{constlastIdAppStorage.getnumber(last_viewed_id)??0// 只需要初始值不需要响应后续变化}四、StorageLink — 双向绑定 AppStorage4.1 基本用法EntryComponentstruct SettingsPage{// StorageLinkAppStorage ↔ 组件双向可读写StorageLink(user_theme)theme:stringlightbuild(){Column(){Toggle({type:ToggleType.Switch,isOn:this.themedark}).onChange((isOn:boolean){// 修改 theme → 自动同步到 AppStorage → 所有订阅者刷新this.themeisOn?dark:light})}}}4.2 跨页面实时同步示例// PageA 设置主题StorageLink(user_theme)themeA:stringlight// 修改 themeA → AppStorage 更新 → PageB 的 themeB 自动刷新// PageB 读取主题无需任何事件监听StorageLink(user_theme)themeB:stringlight五、完整跨页面通信流程5.1 AppListItem → AppDetailPage 完整流程图图1AppListItem 点击 → AppStorage 写入 → 路由跳转 → AppDetailPage 读取的完整链路用户点击列表项 │ ↓ AppListItem.onClick() ├── AppStorage.setOrCreate(current_binding_id, bindingId) ← 写入全局 └── router.pushUrl({ url: pages/AppDetailPage, params: { bindingId } }) │ ↓ 页面路由跳转 │ ↓ AppDetailPage.aboutToAppear() ├── StorageProp 自动读取 current_binding_id ← 主通道 └── router.getParams() 读取 params.bindingId ← 备用通道 │ ↓ this.loadData() → AppBindingDao.findById(bindingId)5.2 完整代码// ── AppListItem.ets发送方──import{promptAction,router}fromkit.ArkUIimport{AppStorage}fromkit.ArkUIComponentexportstruct AppListItem{PropbindingId:number0build(){Row(){/* UI */}.onClick((){if(this.bindingId0){promptAction.showToast({message:数据异常请刷新后重试})return}try{AppStorage.setOrCreatenumber(current_binding_id,this.bindingId)router.pushUrl({url:pages/AppDetailPage,params:{bindingId:this.bindingId}},router.RouterMode.Standard,(err:Error){if(err){promptAction.showToast({message:打开失败${err.message}})}})}catch(e){promptAction.showToast({message:打开失败请重试})}})}}// ── AppDetailPage.ets接收方──import{router}fromkit.ArkUIimport{AppBindingDao}from../features/data/AppBindingDaoimport{AppBindingEntity}from../features/data/ModelsEntryComponentstruct AppDetailPage{StorageProp(current_binding_id)bindingId:number0Stateloading:booleantrueStateloadError:booleanfalseStatebinding:AppBindingEntity|nullnullaboutToAppear():void{// 次通道兜底constparamsrouter.getParams()asRecordstring,numberif(params?.[bindingId]this.bindingId0){this.bindingIdparams[bindingId]}this.loadData()}privateasyncloadData():Promisevoid{if(this.bindingId0){this.loadErrortruethis.loadingfalsereturn}try{this.bindingawaitAppBindingDao.findById(this.bindingId)if(!this.binding){promptAction.showToast({message:该绑定已被删除})router.back()}}catch(e){this.loadErrortrue}finally{this.loadingfalse}}}六、AppStorage 使用规范6.1 键名命名规范// ✅ 使用常量管理键名避免字符串拼写错误exportclassStorageKeys{staticreadonlyCURRENT_BINDING_IDcurrent_binding_idstaticreadonlyUSER_THEMEuser_themestaticreadonlyLAST_VIEWED_CARDlast_viewed_card}// 使用AppStorage.setOrCreatenumber(StorageKeys.CURRENT_BINDING_ID,id)6.2 清理过时数据// 页面销毁时清理临时数据可选aboutToDisappear():void{// 清理避免旧 ID 被下次进入页面时误用AppStorage.delete(current_binding_id)}6.3 不要滥用 AppStorage// ❌ 滥用把所有状态都放 AppStorageAppStorage.setOrCreate(loading,true)// 应该是组件 StateAppStorage.setOrCreate(currentFilter,全部)// 应该是组件 State// ✅ 只存跨页面需要共享的状态AppStorage.setOrCreate(current_binding_id,id)// ✅ 跨页面传参AppStorage.setOrCreate(user_settings,settings)// ✅ 全局偏好七、AppStorage vs PersistentStorage// PersistentStorage持久化到磁盘应用重启后数据不丢失// 必须在 AppStorage 之前初始化PersistentStorage.persistProp(user_theme,light)// 之后通过 AppStorage 操作AppStorage.getstring(user_theme)// 读取已持久化的值// 应用场景对比// AppStorage当次运行中的跨页面传参bindingId 等// PersistentStorage需要持久保存的用户偏好主题、语言等八、本篇小结知识点核心要点AppStorage应用全局 KV 存储进程生命周期非持久化setOrCreate不存在时创建存在时更新StorageProp单向绑定AppStorage → 组件只读StorageLink双向绑定AppStorage ↔ 组件可读写跨页面传参AppStorage 是主通道router params 是备用键名管理用常量类统一管理避免拼写错误参考资料鸿蒙应用开发实战【07】— ArkUI 状态管理全解析鸿蒙应用开发实战【13】— AppListItem 组件实现AppStorage 文档StorageProp 装饰器StorageLink 装饰器PersistentStorage 文档router APILocalStorage 文档如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力相关资源开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.netAppStorage 文档https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-application-state-management-overview状态管理最佳实践https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-state-management-best-practices