HarmonyOS 角落里的知识 —— 状态管理

2024-06-19 02:52

本文主要是介绍HarmonyOS 角落里的知识 —— 状态管理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 一、前言

在探索 HarmonyOS 的过程中,我们发现了许多有趣且实用的功能和特性。有些总是在不经意间或者触类旁通的找到。或者是某些开发痛点。其中,状态管理是ArkUI开发非常核心的一个东西,我们进行了大量的使用和测试遇到了许多奇奇怪怪的问题。

该系列将着重分享、介绍HarmonyOS API11+的新版本特性或者奇奇怪怪的解决方案、BUG。(弃用API非必要不提及)

二、@State

这应该是用的最多的了,状态变量,将状态变量和UI的某个属性绑定,即可同步两者。

  1. 初始化行为

    组件初始化时,@State只能从外面传入一次,之后父组件值的修改并不会影响到组件内部的@State,所以它叫组件内状态~(当然你组件用if、else来更新当我没说)

 @Entry@Componentexport struct ExpComponent {@State title: string = "Title"​build() {Column() {ExpChildComponent({childTitle: this.title})Button(this.title).onClick(()=>{this.title = "Click"})}}}@Componentexport struct ExpChildComponent {@State childTitle: string = "????"​build() {Text(this.childTitle)}}
  1. 就像这样,onClick触发后ExpChildComponent并不会发生改变了。

  2. 太多的@State

    1. 一开始我们会直接将状态变量直接声明在组件中,如:
 @Componentexport struct ExpComponent {@State title: string = ""​build() {Text(this.title)}}

但是随着,一个页面开始变得复杂的时候,我们会面临一堆的Controller,xxState等等,看起来就很头疼。这时候利用@State能观察到Object.keys(自身)返回的所有属性的特性,我们可以抽出一个ExpUIState

 @Componentexport struct ExpComponent {@State uiState: ExpUIState = new ExpUIState()​build() {Text(this.uiState.title)}}​class ExpUIState {title: string = ""}
  1. 如此,还你一个优雅的组件。

  2. 数组

    @State能直接修饰数组:

 @State title: Model[] = [new Model(1), new Model(2)];

数组自身的赋值可以观察到。

 this.title = [new Model(2)];

数组项的赋值可以观察到。

 this.title[0] = new Model(2);

删除数组项可以观察到。

 this.title.pop();

新增数组项可以观察到。

 this.title.push(new Model(12));

数组项中属性的赋值观察不到。

this.title[0].value = 6;
  • 数组对象及其子项的赋值是可以被观察到的,所以“titles[0].value = 1 ”这种使用方法是没用滴。

    4.作用域的影响

  • 得益于闭包的特性(对于Java、Kotlin开发来说不存在的东西)箭头函数体内的this对象,就是定义该函数时所在的作用域指向的对象,而不是使用时所在的作用域指向的对象。

    @Component
    export struct ExpComponent {@State uiState: ExpUIState = new ExpUIState()build() {Column() {Text(this.uiState.title)Button("Click").onClick(()=>{this.uiState.autoRefreshTitle()})}}
    }
    class ExpUIState {title: string = "??"autoRefreshTitle = () => {this.title = "AutoRefreshTitle"}
    }
    

    上述操作,触发onClick是不会更新UI的,如果想要触发更新需要用下面的例子:

@Component
export struct ExpComponent {@State uiState: ExpUIState = new ExpUIState()aboutToAppear(): void {}build() {Column() {Text(this.uiState.title)Button("Click").onClick(()=>{let fk = this.uiStatethis.uiState.autoRefreshTitle(fk)})}}
}
class ExpUIState {title: string = "??"autoRefreshTitle = (st:ExpUIState) => {st.title= "AutoRefreshTitle"}
}
  1. 反人类吧?阿弥陀佛。

  2. 嵌套对象

    @State修饰对象时,里面可能还有对象,或者数组.

class ExpUIState {childs: ExpChild[] = []firstChild: ExpChild = new ExpChild()
}
  1. 很可惜的是,由于@State装饰的变量,只能监听到对象本身的地址以及第一层属性的地址变化,也就是firstChild或者childs地址的变化,例如如下操作:uiState.firstChild.subTtile="",uiState.childs.push(new ExpChild())等是没法触发刷新的。

    解决办法就是不用@State

三、@Prop

  1. 初始化行为

    几乎和@State一致,但是@Prop变量允许在本地修改,但修改后的变化不会同步回父组件。当数据源更改时,@Prop装饰的变量都会更新,并且会覆盖本地所有更改。因此,数值的同步是父组件到子组件(所属组件),子组件数值的变化不会同步到父组件。

    相比起@State重点就是父组件修改后子组件会同步。苦恼@State没法修改的人,有福了~

  2. 套一堆的@Prop

    不要这么做。如果你的子组件使用@Prop、孙子组件也用@Prop,我其实推荐你使用@Provide(当然你硬要用也行)

  3. @Require

    使用@Prop有一个好处就是,可以使用@Require。变成一个必传的参数(福音啊)。@State是可以不传的。

@Require @Prop index: number 

Observed

坏消息:@Prop也没法观察嵌套对象~,因为父组件传入时,用的@State传入的。好消息:加一个@Observed就好了~

@Component
export struct ExpComponent {@State uiState: ExpUIState = new ExpUIState()aboutToAppear(): void {}build() {Column() {ExpChildComponent({child: this.uiState.firstChild})Button("Click").onClick(() => {this.uiState.firstChild.subTitle = "????"})}}
}@Component
export struct ExpChildComponent {@Require @Prop child: ExpChildbuild() {Text(this.child.subTitle)}
}@Observed
class ExpUIState {childs: ExpChild[] = []firstChild: ExpChild = new ExpChild()
}@Observed
class ExpChild {subTitle: string = "啊"
}

在嵌套场景下,每一层都要用@Observed装饰,且每一层都要被@Prop接收。

四、@Link

  1. 初始化行为

    @Link装饰的变量与其父组件中的数据源共享相同的值

    PS:从API version 9开始,@Link子组件从父组件初始化@State的语法为Comp({ aLink: this.aState })。同样Comp({aLink: $aState})也支持(早该如此了)

  2. 给Dialog用

    如果你在某个Dialog中,想同步数据到组件,@Link是一个很好的选择:

 @CustomDialogstruct CustomDialog01 {@Link inputValue: string;controller: CustomDialogController;​build() {Column() {Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 })TextInput({ placeholder: '', text: this.inputValue }).height(60).width('90%').onChange((value: string) => {this.inputValue = value;})}}}​@Entry@Componentstruct DialogDemo01 {@State inputValue: string = 'click me';dialogController: CustomDialogController = new CustomDialogController({builder: CustomDialog01({inputValue: $inputValue})})​build() {Column() {Button(this.inputValue).onClick(() => {this.dialogController.open();}).backgroundColor(0x317aff)}.width('100%').margin({ top: 5 })}}
  1. 当然,你也可以传个函数进去~

  2. @Link套娃

    就像@Prop一样,我很建议你使用@Provide@Consume

五、@Watch

@Watch应用于对状态变量的监听,这个装饰器可以说是非常直观的一个了,就是用来观察状态变量的。

  1. 不要在里面修改状态变量

 @State @Watch("onUiStateChange") uiState: ExpUIState = new ExpUIState()onUiStateChange(){this.uiState.firstChild = new ExpChild()}
  • 相信你看得出来,这是一个死循环吧?

  • 子组件事件传递到父组件

    可通过状态同步@Link@Provide@Consume进行父子组件间的状态通知,结合@Watch可以将状态变量的修改在组件间传递,实现类似的功能。

  • 粘性

    @Watch没有粘性,所以第一次初始化并不会触发@Watch!

  • 日志

    @Watch可以观察状态变量变化的特性,很适合来做Log日志不是吗~



最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。 

鸿蒙HarmonyOS Next全套学习资料←点击领取!(安全链接,放心点击

这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

鸿蒙(HarmonyOS NEXT)最新学习路线

有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

HarmonyOS Next 最新全套视频教程

《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

《鸿蒙开发基础》

  • ArkTS语言
  • 安装DevEco Studio
  • 运用你的第一个ArkTS应用
  • ArkUI声明式UI开发
  • .……

《鸿蒙开发进阶》

  • Stage模型入门
  • 网络管理
  • 数据管理
  • 电话服务
  • 分布式应用开发
  • 通知与窗口管理
  • 多媒体技术
  • 安全技能
  • 任务管理
  • WebGL
  • 国际化开发
  • 应用测试
  • DFX面向未来设计
  • 鸿蒙系统移植和裁剪定制
  • ……

《鸿蒙进阶实战》

  • ArkTS实践
  • UIAbility应用
  • 网络案例
  • ……

大厂面试必问面试题

鸿蒙南向开发技术

鸿蒙APP开发必备

鸿蒙生态应用开发白皮书V2.0PDF



获取以上完整鸿蒙HarmonyOS学习资料,请点击→

总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

这篇关于HarmonyOS 角落里的知识 —— 状态管理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1073809

相关文章

SpringBoot中使用 ThreadLocal 进行多线程上下文管理及注意事项小结

《SpringBoot中使用ThreadLocal进行多线程上下文管理及注意事项小结》本文详细介绍了ThreadLocal的原理、使用场景和示例代码,并在SpringBoot中使用ThreadLo... 目录前言技术积累1.什么是 ThreadLocal2. ThreadLocal 的原理2.1 线程隔离2

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

Java实现状态模式的示例代码

《Java实现状态模式的示例代码》状态模式是一种行为型设计模式,允许对象根据其内部状态改变行为,本文主要介绍了Java实现状态模式的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来... 目录一、简介1、定义2、状态模式的结构二、Java实现案例1、电灯开关状态案例2、番茄工作法状态案例

通过prometheus监控Tomcat运行状态的操作流程

《通过prometheus监控Tomcat运行状态的操作流程》文章介绍了如何安装和配置Tomcat,并使用Prometheus和TomcatExporter来监控Tomcat的运行状态,文章详细讲解了... 目录Tomcat安装配置以及prometheus监控Tomcat一. 安装并配置tomcat1、安装

Linux之进程状态&&进程优先级详解

《Linux之进程状态&&进程优先级详解》文章介绍了操作系统中进程的状态,包括运行状态、阻塞状态和挂起状态,并详细解释了Linux下进程的具体状态及其管理,此外,文章还讨论了进程的优先级、查看和修改进... 目录一、操作系统的进程状态1.1运行状态1.2阻塞状态1.3挂起二、linux下具体的状态三、进程的

Linux内存泄露的原因排查和解决方案(内存管理方法)

《Linux内存泄露的原因排查和解决方案(内存管理方法)》文章主要介绍了运维团队在Linux处理LB服务内存暴涨、内存报警问题的过程,从发现问题、排查原因到制定解决方案,并从中学习了Linux内存管理... 目录一、问题二、排查过程三、解决方案四、内存管理方法1)linux内存寻址2)Linux分页机制3)

高效管理你的Linux系统: Debian操作系统常用命令指南

《高效管理你的Linux系统:Debian操作系统常用命令指南》在Debian操作系统中,了解和掌握常用命令对于提高工作效率和系统管理至关重要,本文将详细介绍Debian的常用命令,帮助读者更好地使... Debian是一个流行的linux发行版,它以其稳定性、强大的软件包管理和丰富的社区资源而闻名。在使用

SpringBoot使用minio进行文件管理的流程步骤

《SpringBoot使用minio进行文件管理的流程步骤》MinIO是一个高性能的对象存储系统,兼容AmazonS3API,该软件设计用于处理非结构化数据,如图片、视频、日志文件以及备份数据等,本文... 目录一、拉取minio镜像二、创建配置文件和上传文件的目录三、启动容器四、浏览器登录 minio五、

IDEA中的Kafka管理神器详解

《IDEA中的Kafka管理神器详解》这款基于IDEA插件实现的Kafka管理工具,能够在本地IDE环境中直接运行,简化了设置流程,为开发者提供了更加紧密集成、高效且直观的Kafka操作体验... 目录免安装:IDEA中的Kafka管理神器!简介安装必要的插件创建 Kafka 连接第一步:创建连接第二步:选

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert