HarmonyOS 鸿蒙Next ArkUI状态管理:@StorageLink装饰器之我的一些经验
HarmonyOS 鸿蒙Next ArkUI状态管理:@StorageLink装饰器之我的一些经验
在声明式UI编程范式中,UI是应用程序状态的函数,开发人员通过修改当前应用程序状态来更新相应的UI界面。
比如@State装饰器,当我们在组件内修改@State变量后,将会自动调用组件的build方法刷新UI
@Entry @Component struct EntryComponent { @State str: string = ‘hello’ build() { Column({ space: 20 }) { Text(this.str).fontSize(30) .onClick(() => { this.str = ‘hello HarmonyOS’ }) } } }当我们点击Text时,onClick事件被触发,此时@State变量str的值被修改为"hello HarmonyOS",build()方法会被重新调用,刷新Text的文本内容,Text的文本内容由"hello"变为"hello HarmonyOS"
@State是我们最常用的UI状态管理的装饰器,用起来很方便,但它同样有这样那样的缺点,比如只能在组件内使用,不能和子组件同步,不支持object,无法持久化。
HarmonyOS为我们提供了@StorageLink装饰器,这个装饰器的功能很强大,但目前在官方文档中描述很少,只能找到下面这一段:
@StorageLink装饰器
组件通过使用@StorageLink(key)装饰的状态变量,将于AppStorage建立双向数据绑定,key为AppStorage中的属性键值。当创建包含@StorageLink的状态变量的组件时,该状态变量的值将使用AppStorage中的值进行初始化,不允许使用本地初始化。在UI组件中对@StorageLink的状态变量所做的更改将同步到AppStorage,并从AppStorage同步到任何其他绑定实例中,如PersistentStorage或其他绑定的UI组件。
这段内容的意思应该是@StorageLink要和AppStorage配合使用,但是AppStorage接口目前还有点问题,上面的功能完全无法体现。
经过多次测试后,我总结出了以下几个@StorageLink的特点:
- @StorageLink(key) 装饰的变量是组件的状态数据,当这些状态数据被修改时,将会调用所在组件的build方法进行UI刷新。
- 一个@StorageLink装饰的数据被修改后,所有相同key的@StorageLink变量都会随之改变,不管你是哪一个页面。
- @StorageLink的作用域是全局的,在应用程序运行期间,在任何页面的任何组件中都可以通过键值访问它的值,它的生命周期取决于应用程序的生命周期。
- 双向同步:在父组件中修改@StorageLink变量会同步到子组件中相同key的@StorageLink变量,反之亦然。
- 所有@StorageLink变量必须初始化。
- @StorageLink支持的数据类型同@State类似,但是它还支持object
- @StorageLink可通过PersistentStorage接口持久化
- 所有相同key的@StorageLink变量,他们的初始值以第一个初始化的值为准
因为文档中没有给@StorageLink起名字,所以根据它的特性,我暂时叫它"组件全局状态"
先来看一个最简单的例子
数据绑定
@Entry @Component struct EntryComponent { @StorageLink(‘key1’) link1: string = ‘hello’ @StorageLink(‘key1’) link2: string = ‘hello’ build() { Column({ space: 20 }) { Text(this.link1).fontSize(30) .onClick(() => { this.link2 = ‘你好’ }) } } } 运行应用,Text的内容显示的是link1的值"hello"
点击Text组件后,link2的值被修改为"你好",此时link1的值也随之变为"你好",build方法被调用,刷新UI,如图:
从上例中可以看出,link1和link2的值是绑定的,不管你修改哪一个值,另一个都会同步修改,同时build方法被调用。
再来看第二个例子:双向同步
@Component struct ChildComponent { @StorageLink(‘key1’) link: string = ‘’ build() { Text(‘child:’ + this.link).fontSize(30).fontColor(Color.Red) .onClick(() => { this.link = ‘你好,鸿蒙’ }) } }
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>@Entry @Component struct EntryComponent { @StorageLink(‘key1’) link1: string = ‘hello’ build() { Column({ space: 20 }) { Text(‘parent:’ + this.link1).fontSize(30).fontColor(Color.Blue) .onClick(() => { this.link1 = ‘hello HarmonyOS’ })
ChildComponent() } .width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>) .alignItems(HorizontalAlign.Center)
} }
我们在入口组件中绑定了键为"key1"的@StorageLink变量link1,在子组件中绑定了相同key的变量link2
当点击父组件的文本时,link1的值被修改,子组件的link2同步变动,父组件和子组件的build方法被调用
当点击子组件的文本时,link2的值被修改,父组件的link1同步变动,子组件和父组件的build方法被调用
第三个例子
页面间通信
// index.ets @Entry @Component struct EntryComponent { @StorageLink(‘key1’) link1: string = ‘hello’
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>build() { Column({ space: 20 }) { Text(this.link1).fontSize(50) .onClick(() => { this.link1 = ‘hello HarmonyOS’ }) // 跳转到page2 Navigator({ target: ‘pages/page2’}) { Button(‘go to page2’).fontSize(30) } } .width(‘100%’) .alignItems(HorizontalAlign.Center) } }
右键new -> eTS Page,创建一个名为page2的页面,代码如下
// page2.ets @Entry @Component struct Page2 { @StorageLink(‘key1’) link: string = ‘’
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>build() { Column({ space: 20 }) { Text(this.link).fontSize(30) .onClick(() => { this.link = “你好鸿蒙” }) // 返回index页面 Navigator({ target: ‘pages/index’, type: NavigationType.Back }) { Button(‘back’).fontSize(30) } } .width(‘100%’) } }
运行效果如图:
第四个例子
持久化
@StorageLink是可以被PersistentStorage接口持久化的,使用起来也非常简单,只要一行就OK了
PersistentStorage.PersistProp(“key1”, “hello”)
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>上面的第一个参数key1就是我们想要持久化的@StorageLink的key,第二个参数是默认值
完整代码如下
PersistentStorage.PersistProp(“key1”, “hello”)
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>@Entry @Component struct EntryComponent { @StorageLink(‘key1’) link1: string = ‘hello’ @StorageLink(‘key1’) link2: string = ‘hello’ build() { Column({ space: 20 }) { Text(this.link1).fontSize(50) .onClick(() => { this.link2 = ‘你好,鸿蒙!’ }) } } }
运行效果:
从示例中我们看到即使应用程序的生命周期结束了,@StorageLink绑定的变量依然是被修改后的值,说明该变量确实被持久化了。
@StorageLink装饰器的功能是很全面的,但是个人觉得最重要的还是它能被PersistentStorage持久化,这一点是@State,@Link,@Prop这些都不能比的。
找HarmonyOS工作还需要会Flutter的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:https://www.bilibili.com/video/BV1S4411E7LY/?p=17
帖子写得真好,太用心了,学习了,谢谢。
有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html
在HarmonyOS鸿蒙Next的ArkUI状态管理中,@StorageLink
装饰器是一个强大的工具,它能够将组件的状态与全局存储(如GlobalContext
中的变量)进行绑定,实现数据的双向绑定与自动同步。以下是我使用@StorageLink
的一些实战经验:
-
简化状态管理:通过
@StorageLink
,你可以直接在模板中访问和修改全局状态,无需手动编写大量的状态更新逻辑,从而简化了状态管理。 -
提高代码可读性:使用
@StorageLink
装饰的变量在模板中清晰明了,其他开发者可以更容易地理解数据流向和状态更新逻辑。 -
性能优化:
@StorageLink
通过底层优化,减少了不必要的状态更新和渲染,从而提高了应用的性能。 -
注意事项:在使用
@StorageLink
时,需要确保全局存储的变量类型与组件中声明的类型一致,以避免类型不匹配导致的错误。此外,当全局状态发生变化时,需要确保相关的组件能够正确响应并更新视图。
总之,@StorageLink
是ArkUI状态管理中的一个重要工具,它能够帮助开发者更高效地管理应用状态。如果在使用过程中遇到问题,建议检查全局存储的变量类型、状态更新逻辑以及组件的响应机制。如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。