文章目录
- 一、简介
- 二、核心概念与用法详解
- 2.1 核心 API 详解
- 三、实战示例:登录 → 个人中心
- 3.1 定义共享数据模型
- 3.2 登录页面(LoginPage)
- 3.3 个人中心页面(ProfilePage)
- 3.4 主页面与页面跳转
- 3.5 运行效果验证
- 四、最佳实践与数据清理
- 五、总结与对比
一、简介
AppStorageV2是 HarmonyOS 提供的应用级全局状态管理方案。它通过键值对方式在应用的所有组件(跨 Ability、跨页面、跨组件层级)之间共享数据,且支持响应式更新——当共享数据发生变化时,所有绑定了该数据的 UI 会自动刷新。
AppStorageV2并非AppStorage的简单升级,而是为状态管理 V2 架构设计的全新全局状态存储方案。
它是为了突破 V1 在响应式能力、数据流方向、与新型组件兼容性上的瓶颈而推出的。旧项目可继续使用AppStorage,但新项目或需要向 V2 架构迁移的项目,官方建议优先使用AppStorageV2,以获得更现代、更可靠的全局状态管理体验。
二、核心概念与用法详解
使用AppStorageV2主要分为三步:
- 定义数据类:创建一个普通类,使用
@ObservedV2装饰器标记它,并用@Trace装饰器标记你希望响应式更新的属性。 - 连接全局存储:在任何一个组件中,使用
AppStorageV2.connect(ClassName, factory)来获取或创建一个与该类绑定的全局单例。 - 读写与响应:直接通过
connect返回的实例读写被@Trace修饰的属性。所有connect了同一个类的组件都会自动收到变化通知并刷新 UI。
注意:如果你希望数据变化后 UI 自动刷新,并且希望获得属性级精准更新、避免无效渲染,那就必须用
@ObservedV2+ @Trace修饰类及其属性。如果你只把AppStorageV2当作一个纯数据容器,且不需要 UI 自动响应内部属性的变化,完全可以去掉装饰器。
2.1 核心 API 详解
@ObservedV2类装饰器
它告诉AppStorageV2系统,这个类是一个可被观察的数据模型。只有被它装饰的类,其实例才能被AppStorageV2管理。
@Trace属性装饰器
标记在类属性上,表示"当这个属性的值发生变化时,需要通知所有观察者"。这是实现响应式的关键。没有被@Trace修饰的属性,即使所属类有@ObservedV2,其变化也不会触发 UI 刷新。
AppStorageV2.connect<T>(type: new () => T, factory: () => T): T
此 API 用于连接到或创建一个指定类型的全局实例。
type: 你定义的、被@ObservedV2装饰的类的构造函数。factory: 一个工厂函数。如果该类型的实例尚不存在于全局存储中,则会调用此函数创建一个新的;如果已存在,则直接返回已存在的实例。
注意:在整个应用进程中,同一个 Class 只会存在一个全局实例(单例模式)。
三、实战示例:登录 → 个人中心
下面通过一个完整的例子,演示如何在登录页写入用户信息,然后在个人中心页读取并展示。你将看到,两页之间无需通过路由传参,数据就能自动同步。
3.1 定义共享数据模型
首先,创建一个独立的文件src/main/ets/model/UserData.ets来存放我们的数据模型。
@ObservedV2exportclassUserData{@Traceusername:string='';@TraceisLoggedIn:boolean=false;}3.2 登录页面(LoginPage)
// src/main/ets/pages/LoginPage.etsimport{AppStorageV2,router}from'@kit.ArkUI';import{UserData}from'../model/UserData';@Entry@ComponentV2exportstruct LoginPage{@LocaluserData:UserData=AppStorageV2.connect(UserData,()=>newUserData())!;@LocalinputValue:string='';build(){Column({space:16}){Text('登录页').fontSize(24).fontWeight(FontWeight.Bold)TextInput({placeholder:'请输入用户名',text:this.inputValue}).onChange((value:string)=>{this.inputValue=value;}).width('80%')Button('登录').width('80%').onClick(()=>{if(this.inputValue.trim().length>0){this.userData.username=this.inputValue.trim();this.userData.isLoggedIn=true;router.push({url:'pages/ProfilePage'})}})}.justifyContent(FlexAlign.Center).width('100%').height('100%')}}关键点:@Local userData通过AppStorageV2.connect初始化。当我们修改this.userData.username时,这个更改会立刻同步到全局存储中。
运行效果:
3.3 个人中心页面(ProfilePage)
// src/main/ets/pages/ProfilePage.etsimport{AppStorageV2}from'@kit.ArkUI';import{UserData}from'../model/UserData';@Entry@ComponentV2exportstruct ProfilePage{@LocaluserData:UserData=AppStorageV2.connect(UserData,()=>newUserData())!;build(){Column({space:16}){Text('个人中心').fontSize(24).fontWeight(FontWeight.Bold)if(this.userData.isLoggedIn){Text(`欢迎您,${this.userData.username}`).fontSize(20).fontColor('#FF6600')}else{Text('未登录').fontSize(18).fontColor(Color.Gray)}}.justifyContent(FlexAlign.Center).width('100%').height('100%')}}关键点:ProfilePage也通过同样的代码AppStorageV2.connect(UserData, () => new UserData())!获取实例。因为UserData类型的全局实例已经在LoginPage中创建,所以这里只会获取并复用同一个实例,从而读取到最新的用户数据。
运行效果:
3.4 主页面与页面跳转
// src/main/ets/pages/Index.etsimport{router}from'@kit.ArkUI';import{AppStorageV2}from'@kit.ArkUI';import{UserData}from'../model/UserData';@Entry@ComponentV2struct Index{@LocaluserData:UserData=AppStorageV2.connect(UserData,()=>newUserData())!;build(){Column({space:20}){Button('去登录').width('80%').onClick(()=>{router.pushUrl({url:'pages/LoginPage'});})Button('去个人中心').width('80%').onClick(()=>{router.pushUrl({url:'pages/ProfilePage'});})}.justifyContent(FlexAlign.Center).width('100%').height('100%')}}运行效果:
3.5 运行效果验证
- 启动应用,点击"去登录"。
- 在登录页输入用户名,点击"登录"。
- 返回主页,点击"去个人中心",你会看到用户名已经自动显示为刚才输入的值。
- 再次回到登录页,修改用户名并再次登录,然后重新进入个人中心,你会发现用户名也同步更新了。整个过程无需任何组件间手动传参。
四、最佳实践与数据清理
AppStorageV2的全局实例与应用进程共存。如果你在登录时存储了用户信息,但在用户退出登录时不清除,那么下次打开应用时,应用可能还会显示上次登录的用户名,这不是我们想要的行为。
因此,强烈建议在用户退出登录时,使用AppStorageV2.remove()方法手动清理数据。
// 在退出登录的方法中调用import{AppStorageV2}from'@kit.arkui';import{UserData}from'../model/UserData';functionlogout(){// ... 执行其他退出逻辑// 移除全局存储中的 UserData 实例AppStorageV2.remove(UserData);}调用remove后,所有connect到UserData的组件都会被通知,并尝试重新通过factory函数创建新的实例,从而恢复到初始状态。
运行效果:
五、总结与对比
| 要点 | 说明 |
|---|---|
需要响应式的属性用@Trace | 只标记你需要响应 UI 变化的属性,避免不必要的性能开销。 |
connect返回的是同一个实例 | 理解这个"单例"特性是正确使用的关键。 |
退出登录时建议remove | 这是数据清理的好习惯,避免旧数据污染新会话。 |
| 生命周期为应用进程级 | 与@State、@Prop等组件级状态管理不同,它是全局的。 |
AppStorageV2非常适合管理全局用户登录状态、应用主题配置、多语言等需要在不同页面间共享的数据。相比于AppStorageV1(使用键值字符串存取),V2版本提供了更现代、类型安全、面向对象的使用方式,是 HarmonyOS 全局状态管理的首选方案。