OpenHarmony应用全局的UI状态存储:AppStorage

AppStorage是应用全局的UI状态存储,是和应用的进程绑定的,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储。

和AppStorage不同的是,LocalStorage是页面级的,通常应用于页面内的数据共享。而AppStorage是应用级的全局状态共享,还相当于整个应用的“中枢”, 持久化数据PersistentStorage 和 环境变量Environment 都是通过AppStorage中转,才可以和UI交互。

本文仅介绍AppStorage使用场景和相关的装饰器:@StorageProp和@StorageLink。

概述

AppStorage是在应用启动的时候会被创建的单例。它的目的是为了提供应用状态数据的中心存储,这些状态数据在应用级别都是可访问的。AppStorage将在应用运行过程保留其属性。属性通过唯一的键字符串值访问。

AppStorage可以和UI组件同步,且可以在应用业务逻辑中被访问。

AppStorage中的属性可以被双向同步,数据可以是存在于本地或远程设备上,并具有不同的功能,比如数据持久化(详见 PersistentStorage )。这些数据是通过业务逻辑中实现,与UI解耦,如果希望这些数据在UI中使用,需要用到 @StorageProp 和 @StorageLink 。

@StorageProp

在上文中已经提到,如果要建立AppStorage和自定义组件的联系,需要使用@StorageProp和@StorageLink装饰器。使用@StorageProp(key)/@StorageLink(key)装饰组件内的变量,key标识了AppStorage的属性。

当自定义组件初始化的时候,会使用AppStorage中对应key的属性值将@StorageProp(key)/@StorageLink(key)装饰的变量初始化。由于应用逻辑的差异,无法确认是否在组件初始化之前向AppStorage实例中存入了对应的属性,所以AppStorage不一定存在key对应的属性,因此@StorageProp(key)/@StorageLink(key)装饰的变量进行本地初始化是必要的。

@StorageProp(key)是和AppStorage中key对应的属性建立单向数据同步,允许本地改变,但是对于@StorageProp,本地的修改永远不会同步回AppStorage中,相反,如果AppStorage给定key的属性发生改变,改变会被同步给@StorageProp,并覆盖掉本地的修改。

装饰器使用规则说明

@StorageProp变量装饰器 说明
装饰器参数 key:常量字符串,必填(字符串需要有引号)。
允许装饰的变量类型 Object class、string、number、boolean、enum类型,以及这些类型的数组。嵌套类型的场景请参考 观察变化和行为表现。
类型必须被指定,建议和AppStorage中对应属性类型相同,否则会发生类型隐式转换,从而导致应用行为异常。不支持any,不允许使用undefined和null。
同步类型 单向同步:从AppStorage的对应属性到组件的状态变量。
组件本地的修改是允许的,但是AppStorage中给定的属性一旦发生变化,将覆盖本地的修改。
被装饰变量的初始值 必须指定,如果AppStorage实例中不存在属性,则作为初始化默认值,并存入AppStorage中。

变量的传递/访问规则说明

传递/访问 说明
从父节点初始化和更新 禁止,@StorageProp不支持从父节点初始化,只能AppStorage中key对应的属性初始化,如果没有对应key的话,将使用本地默认值初始化
初始化子节点 支持,可用于初始化@State、@Link、@Prop、@Provide。
是否支持组件外访问 否。

图1 @StorageProp初始化规则图示

观察变化和行为表现

观察变化

● 当装饰的数据类型为boolean、string、number类型时,可以观察到数值的变化。

● 当装饰的数据类型为class或者Object时,可以观察到赋值和属性赋值的变化,即Object.keys(observedObject)返回的所有属性。

● 当装饰的对象是array时,可以观察到数组添加、删除、更新数组单元的变化。

框架行为

● 当@StorageProp(key)装饰的数值改变被观察到时,修改不会被同步回AppStorage对应属性键值key的属性中。

● 当前@StorageProp(key)单向绑定的数据会被修改,即仅限于当前组件的私有成员变量改变,其他的绑定该key的数据不会同步改变。

● 当@StorageProp(key)装饰的数据本身是状态变量,它的改变虽然不会同步回AppStorage中,但是会引起所属的自定义组件的重新渲染。

● 当AppStorage中key对应的属性发生改变时,会同步给所有@StorageProp(key)装饰的数据,@StorageProp(key)本地的修改将被覆盖。

@StorageLink

@StorageLink(key)是和AppStorage中key对应的属性建立双向数据同步:

1.  本地修改

### 购物车功能开发指南 #### 创建购物车功能的基础环境设置 在 DevEco Studio 中实现购物车功能之前,需要先完成项目的初始化和基础配置。这包括创建一个新的 HarmonyOS 应用程序项目,并确保项目支持 ArkTS 和 ArkUI开发模式[^1]。 ```bash # 打开 DevEco Studio 并新建一个 HarmonyOS 项目 File -> New Project -> Empty Ability (ArkTS) ``` #### 设计购物车页面布局 购物车页面的设计可以通过 ArkUI 提供的组件库来实现。以下是购物车页面的一个简单布局示例: ```typescript // 文件名: ShoppingCartPage.ets @Entry @Component struct ShoppingCartPage { @State cartItems: Array<CartItem> = [ { id: 'item1', name: '商品A', price: 10, quantity: 2 }, { id: 'item2', name: '商品B', price: 20, quantity: 1 } ]; build() { Column({ space: 16 }) { ForEach(this.cartItems, (item) => ( Row({ justifyContent: FlexAlign.SpaceBetween }) { Text(item.name).fontSize(16) Text(`¥${item.price * item.quantity}`).fontSize(16) }.padding(8) )) Button('结算').onClick(() => console.log('前往结算')) }.width('90%') } } interface CartItem { id: string; name: string; price: number; quantity: number; } ``` 此代码片段展示了如何使用 `Column` 和 `Row` 组件构建购物车列表,并通过 `ForEach` 循环展示每件商品的信息[^1]。 #### 实现购物车逻辑 为了使购物车具备动态增删商品的功能,可以扩展上述代码中的状态管理部分。以下是一个简单的购物车逻辑实现: ```typescript // 文件名: ShoppingCartLogic.ts class ShoppingCartService { private items: Map<string, CartItem>; constructor() { this.items = new Map(); } addItem(item: CartItem): void { const existingItem = this.items.get(item.id); if (existingItem) { existingItem.quantity += item.quantity; } else { this.items.set(item.id, item); } } removeItem(itemId: string): void { this.items.delete(itemId); } getCartItems(): Array<CartItem> { return Array.from(this.items.values()); } } const shoppingCartService = new ShoppingCartService(); export function addToCart(item: CartItem): void { shoppingCartService.addItem(item); } export function removeFromCart(itemId: string): void { shoppingCartService.removeItem(itemId); } export function getCartItems(): Array<CartItem> { return shoppingCartService.getCartItems(); } ``` 这段代码实现了购物车服务的核心逻辑,包括添加、删除商品以及获取当前购物车内的商品列表[^2]。 #### 配置多屏适配与响应式渲染 为了让购物车界面能够在不同屏幕尺寸下正常显示,可以采用 OpenHarmony 提供的媒体查询机制。例如,在首页加载时监听屏幕尺寸变化并调整 UI 布局: ```typescript // 文件名: ResponsiveLayout.ets import appStorage from '@ohos.app.storage'; let curBp = ''; function initScreenSizeListener() { const mediaQueryList = mediaquery.matchMediaSync('(min-width: 600px)'); if (mediaQueryList.matches) { curBp = 'md'; } else { curBp = 'sm'; } AppStorage.SetOrCreate('curBp', curBp); } initScreenSizeListener(); ``` 以上代码通过 `matchMediaSync()` 方法检测当前屏幕宽度,并将结果保存到全局存储中以便后续使用[^2]。 #### 订阅购物车事件 如果希望其他模块能够实时感知购物车的变化,则可通过事件订阅的方式通知相关组件。例如: ```typescript // 文件名: EventSubscription.ets import emitter from '@ohos.event.emitter'; emitter.on('addToShoppingCartId', (data) => { console.log('新增商品:', data); }); function emitAddToCartEvent(shoppingCartData) { emitter.emit('addToShoppingCartId', shoppingCartData); } ``` 这里演示了如何利用 `emitter` 模块发送和接收自定义事件[^2]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值