本文转载自《#2023 盲盒 + 码# OpenHarmony 应用 ArkUI 状态管理开发范例》,作者:zhushangyuan_
本文根据 橘子购物应用,实现 ArkUI 中的状态管理。
在声明式 UI 编程框架中,UI 是程序状态的运行结果,用户构建了一个 UI 模型,其中应用的运行时的状态是参数。当参数改变时,UI 作为返回结果,也将进行对应的改变。这些运行时的状态变化所带来的 UI 的重新渲染,在 ArkUI 中统称为状态管理机制。
自定义组件拥有变量,变量必须被装饰器装饰才可以成为状态变量,状态变量的改变会引起 UI 的渲染刷新。如果不使用状态变量,UI 只能在初始化时渲染,后续将不会再刷新。 下图展示了 State 和 View(UI)之间的关系。
@State 装饰的变量,或称为状态变量,一旦变量拥有了状态属性,就和自定义组件的渲染绑定起来。当状态改变时,UI 会发生对应的渲染改变。
在状态变量相关装饰器中,@State 是最基础的,使变量拥有状态属性的装饰器,它也是大部分状态变量的数据源。
子组件中被 @Link 装饰的变量与其父组件中对应的数据源建立双向数据绑定。
@Link 装饰的变量与其父组件中的数据源共享相同的值。
@Componentexport struct DetailPage{@StatecurrentLocation: string = ''}
在父组件 DetailPage 中声明当前定位 currentLocation 变量
Panel(this.isPanel){
Location({isPanel: $isPanel,currentLocation: $currentLocation })
}
将 currentLocation 变量传给子组件 Location
@Componentexport struct Location{@LinkcurrentLocation: string
}
子组件用 @Link 装饰的 currentLocation 接收。
@Builder cityList(city: any){if (this.currentLocation === city.name){List(){
ForEach(city.city, twoCity =>{ListItem(){Column(){
Text(`${twoCity}`)
.width('100%')
.height(30)
.fontSize(14)
.onClick(() =>{ this.currentLocation = city.name +'/'+ twoCity
})
}
}
})
}
.width('100%')
.divider({strokeWidth: 2,color: $r('app.color.divider'),startMargin: 0,endMargin: 20 })
}
}
子组件中的 currentLocation 变量改变会同步父组件中的 currentLocation。
AppStorage 是应用全局的 UI 状态存储,是和应用的进程绑定的,由 UI 框架在应用程序启动时创建,为应用程序 UI 状态属性提供中央存储。
和 LocalStorage 不同的是,LocalStorage 是页面级的,通常应用于页面内的数据共享。而对于 AppStorage,是应用级的全局状态共享。AppStorage 使用场景和相关的装饰器:@StorageProp 和 @StorageLink
@StorageProp (key) 是和 AppStorage 中 key 对应的属性建立单向数据同步,我们允许本地改变的发生,但是对于 @StorageProp,本地的修改永远不会同步回 AppStorage 中,相反,如果 AppStorage 给定 key 的属性发生改变,改变会被同步给 @StorageProp,并覆盖掉本地的修改。
@Entry@Componentstruct HomePage{@StatecurBp: string = 'md'// curBp指当前窗口断点,sm代表小屏,md代表中屏,lg代表大屏}
在 Home.ets 页面中,用 @State 声明当前窗口类型:curBp 变量并赋初值为 md,代表中屏。
isBreakpointSM = (mediaQueryResult) =>{if (mediaQueryResult.matches){ this.curBp = 'sm'
AppStorage.SetOrCreate('curBp', this.curBp)
}
}isBreakpointMD = (mediaQueryResult) =>{if (mediaQueryResult.matches){ this.curBp = 'md'
AppStorage.SetOrCreate('curBp', this.curBp)
}
}isBreakpointLG = (mediaQueryResult) =>{if (mediaQueryResult.matches){ this.curBp = 'lg'
AppStorage.SetOrCreate('curBp', this.curBp)
}
}
根据屏幕尺寸,将 curBp 设置为相应的值,并用 SetOrCreate () 方法保存在 AppStorage 中。
在子组件 NavigationHomePage 中直接使用 curBp 变量
@Entry@Componentexport struct NavigationHomePage{@StorageProp('curBp')curBp: string = 'sm'}
curBp 是根据窗口的尺寸判断的,是不能改变的,因此使用 @StorageProp (‘curBp’) 与 AppStorage (‘curBp’) 建立单向数据同步。
@StorageLink (key) 是和 AppStorage 中 key 对应的属性建立双向数据同步:
1. 本地修改发生,该修改会被同步回AppStorage中; 2. AppStorage中的修改发生后,该修改会被同步到所有绑定AppStorage对应key的属性上,包括单向(@StorageProp和通过Prop创建的单向绑定变量)、双向(@StorageLink和通过Link创建的双向绑定变量)变量和其他实例(比如PersistentStorage)。
@Entry@Componentstruct HomePage{@StorageLink('shoppingCartGoodsList') shoppingCartGoodsList:{data:{id: number }}[] = []
}
在 Home.ets 页面中,用 @StorageLink 装饰器定义 shoppingCartGoodsList,用于获取全局的购物车商品列表。
this.emitterClass.setShoppingCartGoodsList((eventData)=>{ this.shoppingCartGoodsList.push(eventData.data.id)
AppStorage.SetOrCreate('shoppingCartGoodsList', this.shoppingCartGoodsList)
})
使用 AppStorage.SetOrCreate (‘shoppingCartGoodsList’, this.shoppingCartGoodsList) 将购物车商品列表保存在 AppStorage 中。
因为购物车中的商品会联动的变化,比如在商品的详情页将商品添加至购物车,在首页也需要更新购物车信息,因此购物车商品列表采用 @StorageLink 装饰器装饰,与 AppStorage (‘shoppingCartGoodsList’) 建立双向同步。
执行以下命令,可以下载 橘子购物应用工程:
git initgit config core.sparsecheckout trueecho code/Solutions/Shopping/OrangeShopping/ > .git/info/sparse-checkoutgit remote add origin https://gitee.com/openharmony/applications_app_samples.gitgit pull origin master
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70011554/viewspace-2980134/ ,如需转载,请注明出处,否则将追究法律责任。