鸿蒙进阶-状态管理

大家好啊,这里是鸿蒙开天组,今天我们来学习状态管理。

开始组件化开发之后,如何管理组件的状态会变得尤为重要,咱们接下来系统的学习一下这部分的内容

状态管理机制

在声明式UI编程框架中,UI是程序状态的运行结果,用户构建了一个UI模型,其中应用的运行时的状态是参数。当参数改变时,UI作为返回结果,也将进行对应的改变。这些运行时的状态变化所带来的UI的重新渲染,在ArkUI中统称为状态管理机制。

自定义组件拥有变量,变量必须被装饰器装饰才可以成为状态变量,状态变量的改变会引起UI的渲染刷新。如果不使用状态变量,UI只能在初始化时渲染,后续将不会再刷新。 下图展示了State和View(UI)之间的关系。

  • View(UI):UI渲染,指将build方法内的UI描述和@Builder装饰的方法内的UI描述映射到界面。
  • State:状态,指驱动UI更新的数据。用户通过触发组件的事件方法,改变状态数据。状态数据的改变,引起UI的重新渲染。

基本概念

接下来咱们同步一下一些关键词的称呼

  • 状态变量:被状态装饰器装饰的变量,状态变量值的改变会引起UI的渲染更新。示例:@State num: number = 1,其中,@State是状态装饰器,num是状态变量。
  • 常规变量:没有被状态装饰器装饰的变量,通常应用于辅助计算。它的改变永远不会引起UI的刷新。以下示例中increaseBy变量为常规变量。
  • 数据源/同步源:状态变量的原始来源,可以同步给不同的状态数据。通常意义为父组件传给子组件的数据。以下示例中数据源为count: 1。
  • 命名参数机制:父组件通过指定参数传递给子组件的状态变量,为父子传递同步参数的主要手段。示例:CompA: ({ aProp: this.aProp })。
  • 从父组件初始化:父组件使用命名参数机制,将指定参数传递给子组件。子组件初始化的默认值在有父组件传值的情况下,会被覆盖。示例:
@Entry
@Component
struct Parent {build() {Column() {// 从父组件初始化,覆盖本地定义的默认值ChildComponent({ count: 1,})}}
}@Component
struct ChildComponent {// 状态变量,更改会触发 UI 刷新@State count: number = 0;build() {Text(this.count.toString())}
}
  • 初始化子组件:父组件中状态变量可以传递给子组件,初始化子组件对应的状态变量。示例同上。
  • 本地初始化:在变量声明的时候赋值,作为变量的默认值。示例:@State count: number = 0。

装饰器总览

ArkUI提供了多种【装饰器】,通过使用这些装饰器,状态变量不仅可以观察在组件内的改变,还可以在不同组件层级间传递,比如父子组件、跨组件层级,也可以观察全局范围内的变化。根据状态变量的影响范围,将所有的装饰器可以大致分为:

  • 管理组件拥有状态的装饰器:组件级别的状态管理,可以观察组件内变化,和不同组件层级的变化,但需要唯一观察同一个组件树上,即同一个页面内。
  • 管理应用拥有状态的装饰器:应用级别的状态管理,可以观察不同页面,甚至不同UIAbility的状态变化,是应用内全局的状态管理。

下面这张图就是完整的装饰器说明图,咱们后续的学习就围绕着这张图来展开

  1. 管理组件状态:小框中(目前专注这个即可)
  2. 管理应用状态:大框中

@State 自己的状态

@State 装饰器咱们已经学习过了,所以就不从头讲解,而是说2 个使用的注意点

观察变化注意点:

并不是状态变量的所有更改都会引起UI的刷新,只有可以【被框架观察到】的修改才会引起UI刷新。

  • 当装饰的数据类型为boolean、string、number类型时,可以观察到数值的变化。
  • 当装饰的数据类型为class或者Object时,可以观察到自身的赋值的变化,和其属性赋值的变化,即Object.keys(observedObject)返回的所有属性。例子如下。声明ClassA和Model类。
// 基本数据类型
@State count: number = 0;
// 可以观察到数值变化
this.count = 1;//Object.keys 测试interface Chicken {name: stringage: numbercolor: string
}const c: Chicken = {name: '1',age: 2,color: '黄绿色'
}
// 获取对象的属性名,返回字符串数组
console.log('', Object.keys(c))// name,age,color//复杂数据类型且嵌套interface Dog {name: string
}interface Person {name: stringdog: Dog
}@Component
export struct HelloComponent {// 状态变量@State message: string = 'Hello, World!';@State person: Person = {name: 'jack',// 嵌套属性dog: {name: '柯基'}}sayHi() {console.log('你好呀')}build() {Column() {Text(this.message)Button('修改 message').onClick(() => {this.message = 'Hello,ArkTS'})Text(JSON.stringify(this.person))Button('修改title外层属性').onClick(() => {this.person.name = '666'})Button('修改title嵌套属性').onClick(() => {// 修改嵌套属性,无法被监听,UI 不更新this.person.dog.name = '内部的 666'// 修改第一层属性,可以被监听,UI 更新// this.person.dog = {//   name: '阿拉斯加'// }})}}
}

@Prop 父子单向

@Prop 装饰的变量可以和父组件建立单向的同步关系。@Prop 装饰的变量是可变的,但是变化不会同步回其父组件。(不要直接修改 Prop 的值)

@Component
struct SonCom {// 默认值可以省略,不设置为 undefined@Prop xxx:类型='可选默认值' build() {}
}@Entry
@Component// FatherCom 父组件
struct FatherCom {build() {Column() {// 子组件SonCom({xxx:'具体的值'})}}
}

@Link双向同步

使用步骤:

  1. 将父组件的状态属性传递给子组件
  2. 子组件通过@Link修饰即可
  3. 分别测试基础,和复杂类型

基础模板

@Entry
@Component// 父组件
struct KnowledgePage {@State count: number = 0build() {Column() {Text('父组件').fontSize(30)Text(this.count.toString())Button('修改数据').onClick(() => {})SonComponent()}.padding(10).height('100%').backgroundColor('#ccc').width('100%').alignItems(HorizontalAlign.Center).padding({ top: 100 })}
}@Component// 子组件
struct SonComponent {// 编写 UIbuild() {Column({ space: 20 }) {Text('我是子组件').fontSize(20)Column() {Button('修改count').onClick(() => {})}}.backgroundColor('#a6c398').alignItems(HorizontalAlign.Center).width('80%').margin({ top: 100 }).padding(10).borderRadius(10)}
}

参考代码

interface Person {name: stringage: number
}@Entry
@Component// 父组件
struct Page03_Link {@State count: number = 0@State p: Person = {name: 'jack',age: 18,}build() {Column() {Text('父组件').fontSize(30)Text(this.count.toString())Text(JSON.stringify(this.p))Button('修改数据').onClick(() => {this.count--})SonComponent({count: this.count,p: this.p})}.padding(10).height('100%').backgroundColor('#ccc').width('100%').alignItems(HorizontalAlign.Center).padding({ top: 100 })}
}@Component// 子组件
struct SonComponent {// 通过 @Link 来接收@Link count: number@Link p: Person// 编写 UIbuild() {Column({ space: 20 }) {Text('我是子组件').fontSize(20)Text(this.count.toString())Text(JSON.stringify(this.p))Column() {Button('修改count').onClick(() => {this.count++})Button('修改Person').onClick(() => {this.p.age++})}}.backgroundColor('#a6c398').alignItems(HorizontalAlign.Center).width('80%').margin({ top: 100 }).padding(10).borderRadius(10)}
}

好啦,今天的内容就到这里,感谢大家的观看,我们下次再见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/61672.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习每周学习总结J6(ResNeXt-50 算法实战与解析 - 猴痘识别)

🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 | 接辅导、项目定制 目录 0. 总结ResNeXt基本介绍 1. 设置GPU2. 导入数据及处理部分3. 划分数据集4. 模型构建部分5. 设置超参数:定义损失函数&…

IDEA 2024.3 版本更新主要功能介绍

IDEA 2024.3 版本提供的新特性 IntelliJ IDEA 2024.3 的主要新特性: AI Assistant 增强 改进的代码补全和建议更智能的代码分析和重构建议Java 支持改进 支持 Java 21 的所有新特性改进的模式匹配和记录模式支持更好的虚拟线程调试体验开发工具改进 更新的 UI/UX 设…

java基础概念37:正则表达式2-爬虫

一、定义 【回顾】正则表达式的作用 作用一:校验字符串是否满足规则作用二:在一段文本中查找满足要求的内容——爬虫 二、本地爬虫VS网络爬虫 2-1、本地爬虫 示例: 代码优化: public static void main(String[] args) {// 大…

嵌入式AI之rknn yolov5初探

本文主要记录在RK3588上跑通RKNUP的rknn_yolov5_demo的过程,并且对rknn_yolov5_demo的代码进行修改,实现在显示器上同步播放rknn_yolov5_demo视频流检测结果。 首先,是RKNUP SDK的编译,参考官方SDK中的README.md文档,下载好对应的sdk编译工具链,我这边使用的是debian系统…

【数据库批量删除】MySql通过 Procedure 循环删除数据

一、问题描述 在日常使用运维中,一些特殊情况需要批量删除陈旧或异常数据。 如果通过 delete from 【表名】 where 【条件】 直接删除,可能会由于数据量过大,事务执行时间过长,造成死锁。 二、解决方案 通过 Procedure 使用循环…

AmazonS3集成minio实现https访问

最近系统全面升级到https,之前AmazonS3大文件分片上传直接使用http://ip:9000访问minio的方式已然行不通,https服务器访问http资源会报Mixed Content混合内容错误。 一般有两种解决方案,一是升级minio服务,配置ssl证书&#xff0c…

JavaWeb——Mybatis

6. Mybatis MyBatis是一款优秀的持久层框架,用于简化JDBC的开发 6.1. Mybatis入门 6.1.1. 入门程序 6.1.2. JDBC 6.1.3. 数据库连接池 6.1.4. Lombok 6.2. Mybatis基础操作 6.2.1. 删除 6.2.1.1. 根据主键删除 6.2.1.2. 预编译SQL #{id}在编译过程中会替换成?…

【环境配置】ubuntu-jetson上的定时任务

使用 crontab 制定定时任务 目标 每分钟清理当前分钟之前的图片。 [可选]每小时清理当前小时之前的图片。 [可选]每天清理当前日期之前的图片。 [可选] 环境 操作系统:Ubuntu 22.04 (jetson)需要清理的文件夹:/home/nvidia/install/Snapshot 步骤 …

MongoDB数据备份与恢复(内含工具下载、数据处理以及常见问题解决方法)

一、工具准备 对MongoDB进行导入导出、备份恢复等操作时需要用到命令工具,我们要先检查一下MongoDB安装目录下是否有这些工具,正常情况下是没有的:),因为新版本的MongoDB安装时不包含这些工具,需要我们手动下载安装。下载成功之后…

C/C++基础知识复习(27)

1) 移动语义和拷贝语义的区别 拷贝语义和移动语义是C中对象所有权管理的两种机制,主要在对象初始化、赋值或传参时体现。 拷贝语义 (Copy Semantics) 行为:通过深拷贝或浅拷贝,创建一个新对象,并将原对象的值或资源复制到新对象…

学习与理解LabVIEW中多列列表框项名和项首字符串属性

多列列表框控件在如下的位置: 可以对该控件右击,如下位置,即可设置该控件的显示项: 垂直线和水平线指的是上图中组成单元格的竖线和横线(不包括行首列首) 现在介绍该多列列表框的两个属性,分别…

Kafka 数据倾斜:原因、影响与解决方案

Kafka:分布式消息系统的核心原理与安装部署-CSDN博客 自定义 Kafka 脚本 kf-use.sh 的解析与功能与应用示例-CSDN博客 Kafka 生产者全面解析:从基础原理到高级实践-CSDN博客 Kafka 生产者优化与数据处理经验-CSDN博客 Kafka 工作流程解析&#xff1a…

【信息系统项目管理师】第2章:信息技术发展 考点梳理

文章目录 2.1 信息技术及其发展2.1.1 计算机软硬件2.1.2 计算机网络2.1.3 存储和数据库2.1.4 信息安全2.1.5 信息技术的发展 2.2 新一代信息技术及应用2.2.1 物联网2.2.2 云计算2.2.3 大数据2.2.4 区块链2.2.5 人工智能2.2.6 虚拟现实 2.1 信息技术及其发展 2.1.1 计算机软硬件…

《现代制造技术与装备》是什么级别的期刊?是正规期刊吗?能评职称吗?

​问题解答 问:《现代制造技术与装备》是不是核心期刊? 答:不是,是知网收录的第二批认定学术期刊。 问:《现代制造技术与装备》级别? 答:省级。主管单位:齐鲁工业大学&#xff0…

QT:QListView实现table自定义代理

介绍 QListVIew有两种切换形式,QListView::IconMode和QListView::ListMode,通过setViewMode()进行设置切换。因为QListView可以像QTreeView一样显示树形结构,也可以分成多列。这次目标是将ListView的ListMode形态显示为table。使用代理&…

C 语言标准库 - <stdlib.h>

目录 1.类型别名和宏 2.abs(),labs(),llabs() 3.div(),ldiv(),lldiv() 4.字符串转成数值 4.1 a 系列函数 4.2 str 系列函数(浮点数转换) 4.3 str 系列函数(整数转换) 5.rand…

统计学常用的分析方法:T检验

T检验是一种用于比较数据集均值差异的统计方法,包括单样本t检验、配对样本t检验和独立样本t检验,可通过MATLAB、Python和R等工具实现t检验。如果数据不符合正态分布,可考虑使用非参数分析,多余两组数据时,可采用多重比…

STM32通过8位并口驱动TFT-1.8寸屏(ST7735)显示器

TFT1.8寸屏,搭配ST7735驱动芯片,是一种专为小型电子设备设计的彩色液晶显示解决方案。该屏幕采用薄膜晶体管(TFT)技术,能够实现高亮度、高对比度和丰富的色彩表现(即16位色彩深度),提…

win10中使用ffmpeg和MediaMTX 推流rtsp视频

在win10上测试下ffmpeg推流rtsp视频,需要同时用到流媒体服务器MediaMTX 。ffmpeg推流到流媒体服务器MediaMTX ,其他客户端从流媒体服务器拉流。 步骤如下: 1 下载MediaMTX github: Release v1.9.3 bluenviron/mediamtx GitHub​​​​​…

银河麒麟v10 二进制kubeadm+containerd搭建k8s集群(证书100年)—— 筑梦之路

环境说明 银河麒麟v10 x86架构,cgroup v2启用 系统内核:5.4.x 源码编译安装 kubeadm 1.31.2 自编译二进制文件,证书有效期100年 containerd 版本:2.0.0 IPHostnameOS VersionKernel VersionComment192.168.10.100k8s-master…