HarmonyOS 角落里的知识 —— 状态管理
一、前言
在探索 HarmonyOS 的过程中,我们发现了许多有趣且实用的功能和特性。有些总是在不经意间或者触类旁通的找到。或者是某些开发痛点。其中,状态管理是ArkUI开发非常核心的一个东西,我们进行了大量的使用和测试遇到了许多奇奇怪怪的问题。
该系列将着重分享、介绍HarmonyOS API11+的新版本特性或者奇奇怪怪的解决方案、BUG。(弃用API非必要不提及)
二、@State
这应该是用的最多的了,状态变量,将状态变量和UI的某个属性绑定,即可同步两者。
-
初始化行为
组件初始化时,
@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)}}
-
就像这样,
onClick触发后ExpChildComponent并不会发生改变了。 -
太多的@State
- 一开始我们会直接将状态变量直接声明在组件中,如:
@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 = ""}
-
如此,还你一个优雅的组件。
-
数组
@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"}
}
-
反人类吧?阿弥陀佛。
-
嵌套对象
@State修饰对象时,里面可能还有对象,或者数组.
class ExpUIState {childs: ExpChild[] = []firstChild: ExpChild = new ExpChild()
}
-
很可惜的是,由于
@State装饰的变量,只能监听到对象本身的地址以及第一层属性的地址变化,也就是firstChild或者childs地址的变化,例如如下操作:uiState.firstChild.subTtile="",uiState.childs.push(new ExpChild())等是没法触发刷新的。解决办法就是不用@State
三、@Prop
-
初始化行为
几乎和
@State一致,但是@Prop变量允许在本地修改,但修改后的变化不会同步回父组件。当数据源更改时,@Prop装饰的变量都会更新,并且会覆盖本地所有更改。因此,数值的同步是父组件到子组件(所属组件),子组件数值的变化不会同步到父组件。相比起
@State重点就是父组件修改后子组件会同步。苦恼@State没法修改的人,有福了~ -
套一堆的@Prop
不要这么做。如果你的子组件使用
@Prop、孙子组件也用@Prop,我其实推荐你使用@Provide(当然你硬要用也行) -
@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
-
初始化行为
@Link装饰的变量与其父组件中的数据源共享相同的值PS:从API version 9开始,
@Link子组件从父组件初始化@State的语法为Comp({ aLink: this.aState })。同样Comp({aLink: $aState})也支持(早该如此了) -
给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 })}}
-
当然,你也可以传个函数进去~
-
@Link套娃
就像
@Prop一样,我很建议你使用@Provide、@Consume
五、@Watch
@Watch应用于对状态变量的监听,这个装饰器可以说是非常直观的一个了,就是用来观察状态变量的。
-
不要在里面修改状态变量
@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 的过程中,我们发现了许多有趣且实用的功能和特性。有些总是在不经意间或者触类旁通的找到。或者是某些开发痛点。其中,状态管理是ArkUI开发非常核心的一个东西,我们进行了大量的使用和测试遇到了许多奇奇怪怪的问…...
TDengine数据迁移
前言 taosdump 是一个支持从运行中的 TDengine 集群备份数据并将备份的数据恢复到相同或另一个运行中的 TDengine 集群中的工具应用程序。 taosdump 可以用数据库、超级表或普通表作为逻辑数据单元进行备份,也可以对数据库、超级 表和普通表中指定时间段内的数据记录…...
使用ZIP包安装MySQL及配置教程
在本教程中,我们将指导您完成使用ZIP包安装MySQL的过程,并对配置文件进行必要的修改,以及解决可能遇到的问题。本示例以MySQL 5.7.44为例,但步骤同样适用于其他版本如MySQL 8.3.0等。请根据实际需要选择适合的版本下载:…...
Java基础入门day64
day64 web项目 数据库设计 在小米商城主页,主要的内容是多种商品类型的展示,分别有手机,智能穿戴,笔记本平板,家电,生活电器,厨房电器,智能家具等大的七个分类,根据这个…...
高德地图轨迹回放/轨迹播放
前言 本篇文章主要介绍高德地图的轨迹回放或播放的实现过程,是基于vue2实现的功能,同时做一些改动也是能够适配vue3的。其中播放条是用的是element UI中的el-slider组件,包括使用到的图标也是element UI自带的。可以实现轨迹的播放、暂停、停…...
像素、像素密度、位图和矢量图
像素、像素密度、位图和矢量图 像素 -- 图像元素pt分辨率ppidpi 点阵图 - bitmap常见的类型 矢量图点阵图 vs 矢量图参考小结 像素、矢量图等概念在前端开发中经常遇到,这里做一个简单的梳理。 像素 – 图像元素 做前端开发的经常遇到它。像素是图像的最小单位&am…...
第二证券股市资讯:昨夜!全球新“股王”诞生
昨晚,英伟达成全球市值榜首公司。 当地时间6月18日,美股三大指数小幅收高,标普500指数与纳指再创前史新高。标普500指数涨0.25%,道指涨0.15%,纳指涨0.03%。 AI热潮推动英伟达大涨,市值逾越微软、苹果&…...
自动水位雨量站:用于水库防汛预警
TH-SW2自动水位雨量站是一种现代化的监测设备,主要用于水库等水域的防汛预警系统。它通过集成水位和雨量监测功能,为水库的管理和调度提供实时、准确的数据支持。 工作原理: 自动水位雨量站通过内置的水位计和雨量计实时监测水库的水位变化和…...
苍穹外卖---新增员工(P16-P20)
一、需求分析和设计 (1)产品原型 一般在做需求分析时,往往都是对照着产品原型进行分析,因为产品原型比较直观,便于我们理解业务。后台系统中可以管理员工信息,通过新增员工来添加后台系统用户。 新增员工…...
Windows10 利用QT搭建SOEM开发环境
文章目录 一. SOEM库简介二. 安装WinPcap三. SOEM(1.4)库安装(1) 编译32位库(2) 编译64位库 四. 运行SOEM示例代码五. WIN10下利用QT构建SOEM开发环境 一. SOEM库简介 SOEM(Scalable Open EtherCAT Master 或 Simple Open EtherCAT Master)是一个开源的…...
SpringBoot整合H2数据库并将其打包成jar包、转换成exe文件二(补充)
SpringBoot整合H2数据库并将其打包成jar包、转换成exe文件二(补充) 如果你想在cmd命令窗口内看到程序运行,即点开弹出运行窗口,关闭时exe自动关闭。 需要再launch4j上进行如下操作: 这样转换好的exe就可以有控制台了…...
【kyuubi k8s】kyuubi发布k8s执行spark sql
背景 依据上一篇kyuubi与spark集成,并发布spark sql到k8s集群,上一篇的将kyuubi和spark环境放在本地某台服务器上的,为了高可用,本篇将其打包镜像,并发布到k8s。 其实就是将本地的kyuubi,spark࿰…...
机械装配革新者:3D工艺大师智慧赋能,装配无忧
机械装配,简而言之,就是将各个零件和部件按照严格的技术要求组装起来,使之成为完整且符合标准的机械产品。这一过程不仅要求技术操作的精确性,更强调每个零件之间的完美配合,以确保产品的最终质量和性能达到最优。 常规…...
【C++】const和函数参数
一、const 在 C 中,const 关键字用于定义常量。将 const 关键字放在指针的不同位置,其含义也不同。 1、指向常量的指针 const int* ptr; ptr 是一个指向 const int 的指针,ptr 所指向的值不能通过 ptr 修改,但指针本身可以改变…...
2024zjb
单选331/600 下列不属于常用反爬虫手段动是() A访问频度 B验证码校验 C账号权限 D人工筛 题目答案 正确答案:D 330/600 下列不属于聚焦网络爬虫动常用策略动是 A基于深度优先动爬取策略 B基于内容评价动爬取策略 C基于链接结构评价动爬取策略 D基于语境图动爬取策略 题目答案…...
线程池的艺术:深度解析Java多线程并发性能的优化之道
1. 引言 在高并发的Java应用开发中,线程池作为管理和复用线程资源的核心机制,扮演着举足轻重的角色。合理、高效地使用线程池不仅能减少资源消耗、提高系统响应速度,还能有效控制并发线程数量,保证系统的稳定性和性能。 2. 线程池的基本概念与优势 线程池是一种管理和复用…...
Ubuntu server 24 (Linux) 新增磁盘 lvm 动态扩容磁盘空间
1 新增一块硬盘 #查看 sudo fdisk -l #重新分区,转换成lvm类型 sudo fdisk /dev/sdb 2 查看磁盘 df -h3 lvm 配置 #查看lvm逻辑卷 sudo lvdisplay #创建物理卷 sudo pvcreate /dev/sdb1 #扩展卷组 sudo vgextend ubuntu-vg /dev/sdb1 #扩展逻辑卷 sudo lvexte…...
Linux C编译器从零开发三
AST语法树 BNF抽象 expr equality equality relational ("" relational | "!" relational)* relational add ("<" add | "<" add | ">" add | ">" add)* add mul ("" …...
02-ES6新语法
1. ES6 Proxy与Reflect 1.1 概述 Proxy 与 Reflect 是 ES6 为了操作对象引入的 API 。 Proxy 可以对目标对象的读取、函数调用等操作进行拦截,然后进行操作处理。它不直接操作对象,而是像代理模式,通过对象的代理对象进行操作,…...
Vue3中VueRouter基本用法及与Vue2中路由使用差异解析
Vue Router 在 Vue3 中被重写,使用了 Vue3 的 Composition API。使用上跟Vue2 相比有些不同,需要注意。 首先,让我们来看一下 Vue3 中 VueRouter 的基本使用方法: 安装 Vue Router: npm install vue-routernext创建…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...
基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...
