首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

鸿蒙HarmonyOS开发框架—ArkTS语言(状态管理 五)

  • 25-02-22 03:20
  • 4739
  • 6415
blog.csdn.net

管理应用拥有的状态概述

LocalStorage:页面级UI状态存储

LocalStorage是页面级的UI状态存储,通过@Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage也可以在UIAbility内,页面间共享状态。

本文仅介绍LocalStorage使用场景和相关的装饰器:@LocalStorageProp和@LocalStorageLink。

概述

LocalStorage是ArkTS为构建页面级别状态变量提供存储的内存内“数据库”。

  • 应用程序可以创建多个LocalStorage实例,LocalStorage实例可以在页面内共享,也可以通过GetShared接口,获取在UIAbility里创建的GetShared,实现跨页面、UIAbility内共享。
  • 组件树的根节点,即被@Entry装饰的@Component,可以被分配一个LocalStorage实例,此组件的所有子组件实例将自动获得对该LocalStorage实例的访问权限;
  • 被@Component装饰的组件最多可以访问一个LocalStorage实例和AppStorage,未被@Entry装饰的组件不可被独立分配LocalStorage实例,只能接受父组件通过@Entry传递来的LocalStorage实例。一个LocalStorage实例在组件树上可以被分配给多个组件。
  • LocalStorage中的所有属性都是可变的。

应用程序决定LocalStorage对象的生命周期。当应用释放最后一个指向LocalStorage的引用时,比如销毁最后一个自定义组件,LocalStorage将被JS Engine垃圾回收。

LocalStorage根据与@Component装饰的组件的同步类型不同,提供了两个装饰器:

  • @LocalStorageProp:@LocalStorageProp装饰的变量和与LocalStorage中给定属性建立单向同步关系。
  • @LocalStorageLink:@LocalStorageLink装饰的变量和在@Component中创建与LocalStorage中给定属性建立双向同步关系。
限制条件
  • LocalStorage创建后,命名属性的类型不可更改。后续调用Set时必须使用相同类型的值。
  • LocalStorage是页面级存储,GetShared接口仅能获取当前stage,通过​​​​​​​windowStage.loadContent传入的LocalStorage实例,否则返回undefined
@LocalStorageProp

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

当自定义组件初始化的时候,@LocalStorageProp(key)/@LocalStorageLink(key)装饰的变量会通过给定的key,绑定在LocalStorage对应的属性,完成初始化。本地初始化是必要的,因为无法保证LocalStorage一定存在给定的key(这取决于应用逻辑,是否在组件初始化之前在LocalStorage实例中存入对应的属性)。

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

装饰器使用规则说明

@LocalStorageProp变量装饰器

说明

装饰器参数

key:常量字符串,必填(字符串需要有引号)。

允许装饰的变量类型

Object、class、string、number、boolean、enum类型,以及这些类型的数组。 类型必须被指定,且必须和LocalStorage中对应属性相同。不支持any,不允许使用undefined和null。

同步类型

单向同步:从LocalStorage的对应属性到组件的状态变量。组件本地的修改是允许的,但是LocalStorage中给定的属性一旦发生变化,将覆盖本地的修改。

被装饰变量的初始值

必须指定,如果LocalStorage实例中不存在属性,则作为初始化默认值,并存入LocalStorage中。

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

传递/访问

说明

从父节点初始化和更新

禁止,@LocalStorageProp不支持从父节点初始化,只能从LocalStorage中key对应的属性初始化,如果没有对应key的话,将使用本地默认值初始化。

初始化子节点

支持,可用于初始化@State、@Link、@Prop、@Provide。

是否支持组件外访问

否。

图1 @LocalStorageProp初始化规则图示

0000000000011111111.20230821150840.34682417341410361802006688105089:50001231000000:2800:0130448C06428CFEC7AB1A372B29527571D05D841617919A7E51B0ED4C95905E.png

0000000000011111111.20230821150840.34682417341410361802006688105089:50001231000000:2800:0130448C06428CFEC7AB1A372B29527571D05D841617919A7E51B0ED4C95905E.png

观察变化和行为表现

观察变化

  • 当装饰的数据类型为boolean、string、number类型时,可以观察到数值的变化。
  • 当装饰的数据类型为class或者Object时,可以观察到赋值和属性赋值的变化,即Object.keys(observedObject)返回的所有属性。
  • 当装饰的对象是array时,可以观察到数组添加、删除、更新数组单元的变化。

框架行为

  • 当@LocalStorageProp(key)装饰的数值改变被观察到时,修改不会被同步回LocalStorage对应属性键值key的属性中。
  • 当前@LocalStorageProp(key)单向绑定的数据会被修改,即仅限于当前组件的私有成员变量改变,其他的绑定该key的数据不会同步改变。
  • 当@LocalStorageProp(key)装饰的数据本身是状态变量,它的改变虽然不会同步回LocalStorage中,但是会引起所属的自定义组件的重新渲染。
  • 当LocalStorage中key对应的属性发生改变时,会同步给所有@LocalStorageProp(key)装饰的数据,@LocalStorageProp(key)本地的修改将被覆盖。
@LocalStorageLink

如果我们需要将自定义组件的状态变量的更新同步回LocalStorage,就需要用到@LocalStorageLink。

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

  1. 本地修改发生,该修改会被回LocalStorage中;
  2. LocalStorage中的修改发生后,该修改会被同步到所有绑定LocalStorage对应key的属性上,包括单向(@LocalStorageProp和通过prop创建的单向绑定变量)、双向(@LocalStorageLink和通过link创建的双向绑定变量)变量。
装饰器使用规则说明

@LocalStorageLink变量装饰器

说明

装饰器参数

key:常量字符串,必填(字符串需要有引号)。

允许装饰的变量类型

Object、class、string、number、boolean、enum类型,以及这些类型的数组。 类型必须被指定,且必须和LocalStorage中对应属性相同。不支持any,不允许使用undefined和null。

同步类型

双向同步:从LocalStorage的对应属性到自定义组件,从自定义组件到LocalStorage对应属性。

被装饰变量的初始值

必须指定,如果LocalStorage实例中不存在属性,则作为初始化默认值,并存入LocalStorage中。

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

传递/访问

说明

从父节点初始化和更新

禁止,@LocalStorageLink不支持从父节点初始化,只能从LocalStorage中key对应的属性初始化,如果没有对应key的话,将使用本地默认值初始化。

初始化子节点

支持,可用于初始化@State、@Link、@Prop、@Provide。

是否支持组件外访问

否。

图2 @LocalStorageLink初始化规则图示

观察变化和行为表现

观察变化

  • 当装饰的数据类型为boolean、string、number类型时,可以观察到数值的变化。
  • 当装饰的数据类型为class或者Object时,可以观察到赋值和属性赋值的变化,即Object.keys(observedObject)返回的所有属性。
  • 当装饰的对象是array时,可以观察到数组添加、删除、更新数组单元的变化。

框架行为

  1. 当@LocalStorageLink(key)装饰的数值改变被观察到时,修改将被同步回LocalStorage对应属性键值key的属性中。
  2. LocalStorage中属性键值key对应的数据一旦改变,属性键值key绑定的所有的数据(包括双向@LocalStorageLink和单向@LocalStorageProp)都将同步修改;
  3. 当@LocalStorageLink(key)装饰的数据本身是状态变量,它的改变不仅仅会同步回LocalStorage中,还会引起所属的自定义组件的重新渲染。
使用场景
应用逻辑使用LocalStorage
  1. let storage = new LocalStorage({ 'PropA': 47 }); // 创建新实例并使用给定对象初始化
  2. let propA = storage.get('PropA') // propA == 47
  3. let link1 = storage.link('PropA'); // link1.get() == 47
  4. let link2 = storage.link('PropA'); // link2.get() == 47
  5. let prop = storage.prop('PropA'); // prop.get() = 47
  6. link1.set(48); // two-way sync: link1.get() == link2.get() == prop.get() == 48
  7. prop.set(1); // one-way sync: prop.get()=1; but link1.get() == link2.get() == 48
  8. link1.set(49); // two-way sync: link1.get() == link2.get() == prop.get() == 49

复制

从UI内部使用LocalStorage

除了应用程序逻辑使用LocalStorage,还可以借助LocalStorage相关的两个装饰器@LocalStorageProp和@LocalStorageLink,在UI组件内部获取到LocalStorage实例中存储的状态变量。

本示例以@LocalStorage为例,展示了:

  • 使用构造函数创建LocalStorage实例storage;
  • 使用@Entry装饰器将storage添加到CompA顶层组件中;
  • @LocalStorageLink绑定LocalStorage对给定的属性,建立双向数据同步。
  1. // 创建新实例并使用给定对象初始化
  2. let storage = new LocalStorage({ 'PropA': 47 });
  3. @Component
  4. struct Child {
  5. // @LocalStorageLink变量装饰器与LocalStorage中的'ProA'属性建立双向绑定
  6. @LocalStorageLink('PropA') storLink2: number = 1;
  7. build() {
  8. Button(`Child from LocalStorage ${this.storLink2}`)
  9. // 更改将同步至LocalStorage中的'ProA'以及Parent.storLink1
  10. .onClick(() => this.storLink2 += 1)
  11. }
  12. }
  13. // 使LocalStorage可从@Component组件访问
  14. @Entry(storage)
  15. @Component
  16. struct CompA {
  17. // @LocalStorageLink变量装饰器与LocalStorage中的'ProA'属性建立双向绑定
  18. @LocalStorageLink('PropA') storLink1: number = 1;
  19. build() {
  20. Column({ space: 15 }) {
  21. Button(`Parent from LocalStorage ${this.storLink1}`) // initial value from LocalStorage will be 47, because 'PropA' initialized already
  22. .onClick(() => this.storLink1 += 1)
  23. // @Component子组件自动获得对CompA LocalStorage实例的访问权限。
  24. Child()
  25. }
  26. }
  27. }

复制

@LocalStorageProp和LocalStorage单向同步的简单场景

在下面的示例中,CompA 组件和Child组件分别在本地创建了与storage的'PropA'对应属性的单向同步的数据,我们可以看到:

  • CompA中对this.storProp1的修改,只会在CompA中生效,并没有同步回storage;
  • Child组件中,Text绑定的storProp2 依旧显示47。
  1. // 创建新实例并使用给定对象初始化
  2. let storage = new LocalStorage({ 'PropA': 47 });
  3. // 使LocalStorage可从@Component组件访问
  4. @Entry(storage)
  5. @Component
  6. struct CompA {
  7. // @LocalStorageProp变量装饰器与LocalStorage中的'ProA'属性建立单向绑定
  8. @LocalStorageProp('PropA') storProp1: number = 1;
  9. build() {
  10. Column({ space: 15 }) {
  11. // 点击后从47开始加1,只改变当前组件显示的storProp1,不会同步到LocalStorage中
  12. Button(`Parent from LocalStorage ${this.storProp1}`)
  13. .onClick(() => this.storProp1 += 1)
  14. Child()
  15. }
  16. }
  17. }
  18. @Component
  19. struct Child {
  20. // @LocalStorageProp变量装饰器与LocalStorage中的'ProA'属性建立单向绑定
  21. @LocalStorageProp('PropA') storProp2: number = 2;
  22. build() {
  23. Column({ space: 15 }) {
  24. // 当CompA改变时,当前storProp2不会改变,显示47
  25. Text(`Parent from LocalStorage ${this.storProp2}`)
  26. }
  27. }
  28. }

复制

@LocalStorageLink和LocalStorage双向同步的简单场景

下面的示例展示了@LocalStorageLink装饰的数据和LocalStorage双向同步的场景

  1. // 构造LocalStorage实例
  2. let storage = new LocalStorage({ 'PropA': 47 });
  3. // 调用link9+接口构造'PropA'的双向同步数据,linkToPropA 是全部变量
  4. let linkToPropA = storage.link('PropA');
  5. @Entry(storage)
  6. @Component
  7. struct CompA {
  8. // @LocalStorageLink('PropA')在CompA自定义组件中创建'PropA'的双向同步数据,初始值为47,因为在构造LocalStorage已经给“PropA”设置47
  9. @LocalStorageLink('PropA') storLink: number = 1;
  10. build() {
  11. Column() {
  12. Text(`incr @LocalStorageLink variable`)
  13. // 点击“incr @LocalStorageLink variable”,this.storLink加1,改变同步回storage,全局变量linkToPropA也会同步改变
  14. .onClick(() => this.storLink += 1)
  15. // 并不建议在组件内使用全局变量linkToPropA.get(),因为可能会有生命周期不同引起的错误。
  16. Text(`@LocalStorageLink: ${this.storLink} - linkToPropA: ${linkToPropA.get()}`)
  17. }
  18. }
  19. }

复制

兄弟节点之间同步状态变量

下面的示例展示了通过@LocalStorageLink双向同步兄弟节点之间的状态。

先看Parent自定义组件中发生的变化:

  1. 点击“playCount ${this.playCount} dec by 1”,this.playCount减1,修改同步回LocalStorage中,Child组件中的playCountLink绑定的组件会同步刷新;
  2. 点击“countStorage ${this.playCount} incr by 1”,调用LocalStorage的set接口,更新LocalStorage中“countStorage”对应的属性,Child组件中的playCountLink绑定的组件会同步刷新;
  3. Text组件“playCount in LocalStorage for debug ${storage.get('countStorage')}”没有同步刷新,原因是因为storage.get('countStorage')返回的是常规变量,常规变量的更新并不会引起Text组件的重新渲染。

Child自定义组件中的变化:

  1. playCountLink的刷新会同步回LocalStorage,并且引起兄弟组件和父组件相应的刷新。
  1. let storage = new LocalStorage({ countStorage: 1 });
  2. @Component
  3. struct Child {
  4. // 子组件实例的名字
  5. label: string = 'no name';
  6. // 和LocalStorage中“countStorage”的双向绑定数据
  7. @LocalStorageLink('countStorage') playCountLink: number = 0;
  8. build() {
  9. Row() {
  10. Text(this.label)
  11. .width(50).height(60).fontSize(12)
  12. Text(`playCountLink ${this.playCountLink}: inc by 1`)
  13. .onClick(() => {
  14. this.playCountLink += 1;
  15. })
  16. .width(200).height(60).fontSize(12)
  17. }.width(300).height(60)
  18. }
  19. }
  20. @Entry(storage)
  21. @Component
  22. struct Parent {
  23. @LocalStorageLink('countStorage') playCount: number = 0;
  24. build() {
  25. Column() {
  26. Row() {
  27. Text('Parent')
  28. .width(50).height(60).fontSize(12)
  29. Text(`playCount ${this.playCount} dec by 1`)
  30. .onClick(() => {
  31. this.playCount -= 1;
  32. })
  33. .width(250).height(60).fontSize(12)
  34. }.width(300).height(60)
  35. Row() {
  36. Text('LocalStorage')
  37. .width(50).height(60).fontSize(12)
  38. Text(`countStorage ${this.playCount} incr by 1`)
  39. .onClick(() => {
  40. storage.set<number>('countStorage', 1 + storage.get<number>('countStorage'));
  41. })
  42. .width(250).height(60).fontSize(12)
  43. }.width(300).height(60)
  44. Child({ label: 'ChildA' })
  45. Child({ label: 'ChildB' })
  46. Text(`playCount in LocalStorage for debug ${storage.get<number>('countStorage')}`)
  47. .width(300).height(60).fontSize(12)
  48. }
  49. }
  50. }

复制

将LocalStorage实例从UIAbility共享到一个或多个视图

上面的实例中,LocalStorage的实例仅仅在一个@Entry装饰的组件和其所属的子组件(一个页面)中共享,如果希望其在多个视图中共享,可以在所属UIAbility中创建LocalStorage实例,并调用windowStage.​​​​​​​loadContent。

  1. // EntryAbility.ts
  2. import UIAbility from '@ohos.app.ability.UIAbility';
  3. import window from '@ohos.window';
  4. export default class EntryAbility extends UIAbility {
  5. storage: LocalStorage = new LocalStorage({
  6. 'PropA': 47
  7. });
  8. onWindowStageCreate(windowStage: window.WindowStage) {
  9. windowStage.loadContent('pages/Index', this.storage);
  10. }
  11. }

复制

在UI页面通过GetShared接口获取在通过loadContent共享的LocalStorage实例。

  1. // 通过GetShared接口获取stage共享的Storage实例
  2. let storage = LocalStorage.GetShared()
  3. @Entry(storage)
  4. @Component
  5. struct CompA {
  6. // can access LocalStorage instance using
  7. // @LocalStorageLink/Prop decorated variables
  8. @LocalStorageLink('PropA') varA: number = 1;
  9. build() {
  10. Column() {
  11. Text(`${this.varA}`).fontSize(50)
  12. }
  13. }
  14. }

最后,为了能让大家更好的去学习提升鸿蒙 (Harmony OS) 开发技术,小编连夜整理了一份30个G纯血版学习资料(含视频、电子书、学习文档等)以及一份在Github上持续爆火霸榜的《纯血版华为鸿蒙 (Harmony OS)开发手册》(共计890页),希望对大家有所帮助。

纯血版鸿蒙 HarmonyOS 4.0 视频学习资料

 需要以上视频学习资料小伙伴

请点击→纯血版全套鸿蒙HarmonyOS学习资料


《纯血版华为鸿蒙 (Harmony OS)开发手册》

这份手册涵盖了当前鸿蒙 (Harmony OS) 开发技术必掌握的核心知识点

纯血版鸿蒙 (Harmony OS)开发手册部分精彩内容

HarmonyOS 概念:

  • 系统定义
  • 技术架构
  • 技术特性
  • 系统安全

如何快速入门?

  • 基本概念
  • 构建第一个ArkTS应用
  • 构建第一个JS应用
  • ……


开发基础知识: 

  • 应用基础知识
  • 配置文件
  • 应用数据管理
  • 应用安全管理
  • 应用隐私保护
  • 三方应用调用管控机制
  • 资源分类与访问
  • 学习ArkTS语言
  • ……

基于ArkTS 开发:

  • Ability开发
  • UI开发
  • 公共事件与通知
  • 窗口管理
  • 媒体
  • 安全
  • 网络与链接
  • 电话服务
  • 数据管理
  • 后台任务(Background Task)管理
  • 设备管理
  • 设备使用信息统计
  • DFX
  • 国际化开发
  • 折叠屏系列
  • .……

获取以上文中提到的这份纯血版鸿蒙 (Harmony OS) 开发资料的小伙伴 

请点击→纯血版全套鸿蒙HarmonyOS学习资料


?写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing?,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新VIP学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料

最新鸿蒙Next全套学习资料请扫码
微信名片
注:本文转载自blog.csdn.net的蜀道山QAQ的文章"https://blog.csdn.net/shudaoshanQAQ/article/details/135637399"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top