鸿蒙Harmony–状态管理器–@State详解

devtools/2025/2/5 9:52:03/

鸿蒙Harmony–状态管理器–@State详解

1.1 定义

@State装饰的变量,或者称为状态变量,一旦变量拥有了状态属性,就可以触发其直接绑定UI组件的刷新。当状态改变时,UI会发生对应的渲染变化 ,@State装饰的变量,与声明式范式中的其他被装饰变量一样,是私有的,只能从组件内部访问。在声明时候必须本地初始化

1.1.1 案例演示

  1. 代码示意
import { promptAction } from '@kit.ArkUI'@Entry
@Component
struct Test {num: number = 1build() {Column() {Row({space:20}) {Button('+').onClick(()=>{this.num++promptAction.showToast({message:this.num+''})})Text(this.num + '')Button('-').onClick(()=>{this.num--promptAction.showToast({message:this.num+''})})}}.width('100%').height('100%')}
}
  1. 演示

如下图显示,点击Button按钮,UI界面并不会更新,但是我们通过弹层提示是可以明显看到数据变化了的,

img

  1. 加上@State装饰器后的正确效果
import { promptAction } from '@kit.ArkUI'@Entry
@Component
struct Test {@Statenum: number = 1build() {Column() {Row({space:20}) {Button('+').onClick(()=>{this.num++promptAction.showToast({message:this.num+''})})Text(this.num + '')Button('-').onClick(()=>{this.num--promptAction.showToast({message:this.num+''})})}}.width('100%').height('100%')}
}

img

通过上述案例,我们可以得出结论,@State装饰器修饰的数据变化可以让UI发生变化,但是在鸿蒙中,@State装饰器也有限制。在修饰引用数据的时候,@State装饰器只能监测对象自身和第一层的变化

1.2@State装饰器的限制以及解决办法

1.2.1限制

@State修饰引用类型的数据时候,只能在自身或者第一层发生变化的时候产生更新

  1. 案例
import { promptAction } from '@kit.ArkUI';@Entry
@Component
struct Test01 {//1.数据驱动UI变化  加上@State装饰器@StatepersionInfo: PersionInfo = {name: '小程',age: '21',sex: '女',address: {province: '安徽',city: '黄山市',area: '黄山'}}build() {Column() {Row() {Text('姓名:')TextInput({ text: this.persionInfo.name }).layoutWeight(1)}.width('100%').padding(20)Row() {Text('年龄:')TextInput({ text: this.persionInfo.age }).layoutWeight(1)}.width('100%').padding(20)Row() {Text('性别:')TextInput({ text: this.persionInfo.sex }).layoutWeight(1)}.width('100%').padding(20)Row({ space: 10 }) {Text('地址:')TextInput({ text: this.persionInfo.address.province }).layoutWeight(1)TextInput({ text: this.persionInfo.address.city }).layoutWeight(1)TextInput({ text: this.persionInfo.address.area }).layoutWeight(1)}.width('100%').padding(20)Row({ space: 20 }) {Button('改变姓名').onClick(() => {this.persionInfo.name = '小程神'})Button('改变省份').onClick(() => {this.persionInfo.address.province = '河北'promptAction.showToast({message: JSON.stringify(this.persionInfo.address)})})}}.width('100%').height('100%')}
}interface Address {province: stringcity: stringarea: string
}interface PersionInfo {name: stringage: stringsex: '男' | '女'address: Address
}
  1. 效果展示

img

  1. 案例分析
  • 在我们修改姓名的时候,姓名也是成功修改,但是我们在修改省份的时候,却没有成功修改,但是数据其实更改的了,但是UI层并没有更新,这就涉及到了鸿蒙里面@State装饰器修饰的引用数据只能修改本身或者第一层数据,而省份是在address里面的第二层,所以自然不会刷新,所以通过修改自身和第一层我们可以更新省份

1.2.2解决方法

  1. 方法一:修改第一层
  • 代码
 Button('改变省份').onClick(() => {this.persionInfo.address = {province:'河北',city:'保定',area:'莲池区'}promptAction.showToast({message: JSON.stringify(this.persionInfo.address)})})
  • 效果展示

img

2.方法二:修改自身

  • 代码演示
     Button('改变省份').onClick(() => {// this.persionInfo.address = {//   province:'河北',//   city:'保定',//   area:'莲池区'// }this.persionInfo={name: '小程',age: '21',sex: '女',address: {province: '河北',city: '黄山市',area: '黄山'}}promptAction.showToast({message: JSON.stringify(this.persionInfo.address)})})
  • 效果展示

img

通过上述方法,我们可以总结为UI更新的原理就是产生了一个新对象,得到一个新对象,UI就会更新,另辟蹊径,我们可以把接口转换为类,然后new一个对象去赋值,然后更新UI

  1. 方法三:new 一个新对象
  • 代码展示
export class AddressModel implements Address {province: string = ''city: string = ''area: string = ''constructor(model: Address) {this.province = model.provincethis.city = model.citythis.area = model.area}
}
export class PersionInfoModel implements PersionInfo {name: string = ''age: string = ''sex: '男' | '女' = '男'address: Address = new AddressModel({} as Address)constructor(model: PersionInfo) {this.name = model.namethis.age = model.agethis.sex = model.sexthis.address = model.address}
}Button('改变省份').onClick(() => {// this.persionInfo.address = {//   province:'河北',//   city:'保定',//   area:'莲池区'// }// this.persionInfo={//   name: '小程',//   age: '21',//   sex: '女',//   address: {//     province: '河北',//     city: '黄山市',//     area: '黄山'//   }//// }this.persionInfo.address.province = '四川'this.persionInfo = new PersionInfoModel(this.persionInfo)promptAction.showToast({message: JSON.stringify(this.persionInfo.address)})
  • 效果展示

img

1.3总结

  1. @State装饰器可以通过数据驱动视图更新
  2. 在鸿蒙中,@State只能监听到引用数据的本身和第一层,不能监听到第二层
  3. 如果想监听到第二层以及第二层往后,可以改变数据的本身、第一层或者new一个新对象

http://www.ppmy.cn/devtools/156238.html

相关文章

交叉验证、精确率、召回率

1. 交叉验证 交叉验证是在机器学习建立模型和验证模型参数时常用的办法。交叉验证,顾名思义,就是重复的使用数据,把得到的样本数据进行切分,组合为不同的训练集和测试集,用训练集来训练模型,用测试集来评估…

数据结构:树和二叉树概念_堆篇

图均为博主手绘 , 代码基于vs2022实现 系列文章目录 数据结构:时间复杂度 数据结构初探: 顺序表 数据结构初探:链表之单链表篇 数据结构初探:链表之双向链表篇 链表特别篇:链表经典算法问题 数据结构:栈篇 数据结构:队列篇 栈和队列特别篇:栈和队列的经典算法问题 文章目录 系…

Kamailio、MySQL、Redis、Gin后端、Vue.js前端等基于容器化部署

基于容器化的部署方案,通常会将每个核心服务(如Kamailio、MySQL、Redis、Gin后端、Vue.js前端等)独立运行在不同的容器中,通过Docker或Kubernetes统一管理。以下是具体实现方式和关键原因: 1. 容器化部署的核心思路 每…

Oracle Primavera P6 最新版 v24.12 更新 2/2

目录 一. 引言 二. P6 EPPM 更新内容 1. 用户管理改进 2. 更轻松地标准化用户设置 3. 摘要栏标签汇总数据字段 4. 将里程碑和剩余最早开始日期拖到甘特图上 5. 轻松访问审计数据 6. 粘贴数据时排除安全代码 7. 改进了状态更新卡片视图中的筛选功能 8. 直接从活动电子…

Vue 图片引用方式详解:静态资源与动态路径访问

目录 前言1. 引用 public/ 目录2. assets/ 目录3. 远程服务器4. Vue Router 动态访问5. 总结6. 扩展(图片不显示) 前言 🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF 在 Vue 开发中&#x…

【技海登峰】Kafka漫谈系列(二)Kafka高可用副本的数据同步与选主机制

【技海登峰】Kafka漫谈系列(二)Kafka高可用副本的数据同步与选主机制 一. 数据同步 有了副本Replica的概念,我们还需要面临一个设计难题即:如何处理分区中Leader与Follwer节点数据同步不匹配问题所带来的风险,这也是保证数据高可用的一个方面。 1. ISR伸缩机制 ISR(In-…

自制虚拟机(C/C++)(一、分析语法和easyx运用,完整虚拟机实现)

网上对虚拟机的解释很多,其实本质就一句话 虚拟机就是机器语言解释器 我们今天要实现汇编语言解释器,下一次再加上ndisasm反汇编器就是真正虚拟机了 注:这里的虚拟机指的是VMware一类的,而不是JVM,python一样的高级语言解释器 …

第26篇 基于ARM A9处理器用C语言实现中断<二>

Q:基于ARM A9处理器怎样编写C语言工程,使用按键中断将数字显示在七段数码管上呢? A:基本原理:主程序需要首先调用子程序set_A9_IRQ_stack()初始化IRQ模式的ARM A9堆栈指针;然后主程序调用子程序config_GIC…