鸿蒙Harmony--状态管理器-@Observed装饰器和@ObjectLink装饰器详解
经历的越多,越喜欢简单的生活,干净的东西,清楚的感觉,有结果的事,和说到做到的人。把圈子变小,把语放缓,把心放宽,用心做好手边的事儿,该有的总会有的!
目录
一,定义
二,装饰器说明
三,变量的传递/访问规则说明
四,使用
1,简单对象的使用
2,嵌套对象的使用
3,数组对象的使用
一,定义
之前所讲的装饰器仅能观察到第一层的变化,但是在实际应用开发中,应用会根据开发需要,封装自己的数据模型。对于多层嵌套的情况,比如二维数组,或者数组项class,或者class的属性是class,他们的第二层的属性变化是无法观察到的。这就引出了@Observed/@ObjectLink装饰器。
@ObjectLink和@Observed类装饰器用于在涉及嵌套对象或数组的场景中进行双向数据同步:
①被@Observed装饰的类,可以被观察到属性的变化;
②子组件中@ObjectLink装饰器装饰的状态变量用于接收@Observed装饰的类的实例,和父组件中对应的状态变量建立双向数据绑定。这个实例可以是数组中的被@Observed装饰的项,或者是class object中的属性,这个属性同样也需要被@Observed装饰。
③单独使用@Observed是没有任何作用的,需要搭配@ObjectLink或者@Prop使用。
限制条件:
①使用@Observed装饰class会改变class原始的原型链,@Observed和其他类装饰器装饰同一个class可能会带来问题。
②@ObjectLink装饰器不能在@Entry装饰的自定义组件中使用。
二,装饰器说明
| @Observed类装饰器 | 说明 |
|---|---|
| 装饰器参数 | 无 |
| 类装饰器 | 装饰class。需要放在class的定义前,使用new创建类对象。 |
| @ObjectLink变量装饰器 | 说明 |
|---|---|
| 装饰器参数 | 无 |
| 同步类型 | 不与父组件中的任何类型同步变量。 |
| 允许装饰的变量类型 | 必须为被@Observed装饰的class实例,必须指定类型。 不支持简单类型,可以使用@Prop。 支持继承Date或者Array的class实例 @ObjectLink的属性是可以改变的,但是变量的分配是不允许的,也就是说这个装饰器装饰变量是只读的,不能被改变。 |
| 被装饰变量的初始值 | 不允许。 |
!注意:
@ObjectLink装饰的变量不能被赋值,如果要使用赋值操作,请使用@Prop。
①@Prop装饰的变量和数据源的关系是单向同步,@Prop装饰的变量在本地拷贝了数据源,所以它允许本地更改,如果父组件中的数据源有更新,@Prop装饰的变量本地的修改将被覆盖;
②@ObjectLink装饰的变量和数据源的关系是双向同步,@ObjectLink装饰的变量相当于指向数据源的指针。禁止对@ObjectLink装饰的变量赋值,如果一旦发生@ObjectLink装饰的变量的赋值,则同步链将被打断。因为@ObjectLink修饰的变量通过数据源(Object)引用来初始化。对于实现双向数据同步的@ObjectLink,赋值相当于更新父组件中的数组项或者class的属性,TypeScript/JavaScript不能实现,会发生运行时报错。
三,变量的传递/访问规则说明
| @ObjectLink传递/访问 | 说明 |
|---|---|
| 从父组件初始化 | 必须指定。 初始化@ObjectLink装饰的变量必须同时满足以下场景: - 类型必须是@Observed装饰的class。 - 初始化的数值需要是数组项,或者class的属性。 - 同步源的class或者数组必须是@State,@Link,@Provide,@Consume或者@ObjectLink装饰的数据。 |
| 与源对象同步 | 双向。 |
| 可以初始化子组件 | 允许,可用于初始化常规变量、@State、@Link、@Prop、@Provide |
四,使用
注意,@Observed必须在ets文件中使用,在ts文件中不允许使用
1,简单对象的使用
用@Observed装饰数据类
@Observed
export default class YuanZhen {public name: string = 'YuanZhen';public age: number = 18;constructor(name: string, age: number) {this.name = namethis.age = age}
}
子组件
import YuanZhen from './bean/YuanZhen'@Component
export default struct ProvideTest {@ObjectLink yuanZhen:YuanZhenbuild() {Row() {Column() {Text("子name:" + this.yuanZhen.name+"\nage:"+this.yuanZhen.age).fontSize(50).fontWeight(FontWeight.Bold).onClick(() => {this.yuanZhen.name ="袁震2"this.yuanZhen.age=35})}.width('100%')}.height('100%')}}
父组件
import YuanZhen from './bean/YuanZhen';
import ProvideTest from './ProvideTest';@Entry
@Component
struct Index {@State yuan:YuanZhen=new YuanZhen("袁震",18)build() {Column(){Text("父name:" + this.yuan.name+"\nage:"+this.yuan.age).fontSize(50).fontWeight(FontWeight.Bold).onClick(() => {this.yuan.name ="袁震1"this.yuan.age =20})ProvideTest({yuanZhen:this.yuan})}}}
注意:这里会有一个报错,Assigning the '@State' decorated attribute 'yuan' to the '@ObjectLink' decorated attribute 'yuanZhen' is not allowed. <ArkTSCheck> 是编译器的问题,但是不影响使用
运行效果:
点击父
点击子
所以, 被@Observed和@ObjectLink修饰的class可以实现父子双向绑定
2,嵌套对象的使用
用@Observed修饰的数据类:
@Observed
export default class YuanZhen {public name: string = 'YuanZhen';public age: number = 18;constructor(name: string, age: number) {this.name = namethis.age = age}
}
import YuanZhen from './YuanZhen';
@Observed
export default class Yuan {public number: number = 1;public yuanZhen: YuanZhen = new YuanZhen('yuanzhen', 18);constructor(number: number, yuanZhen: YuanZhen) {this.number = numberthis.yuanZhen = yuanZhen}
}
子组件:
import YuanZhen from './bean/YuanZhen'@Component
export default struct ProvideTest {@ObjectLink yuanZhen:YuanZhenbuild() {Row() {Column() {Text("子name:" + this.yuanZhen.name+"\nage:"+this.yuanZhen.age).fontSize(50).fontWeight(FontWeight.Bold).onClick(() => {this.yuanZhen.name ="袁震2"this.yuanZhen.age=35})}.width('100%')}.height('100%')}
}
父组件:
import Yuan from './bean/Yuan';
import YuanZhen from './bean/YuanZhen';
import ProvideTest from './ProvideTest';@Entry
@Component
struct Index {@State yuan:Yuan=new Yuan(1,new YuanZhen("袁震",18))build() {Column(){Text("父name:" + this.yuan.yuanZhen.name+"\nage:"+this.yuan.yuanZhen.age).fontSize(50).fontWeight(FontWeight.Bold).onClick(() => {this.yuan.yuanZhen.name ="袁震1"this.yuan.yuanZhen.age =20console.info("yz----name="+this.yuan.yuanZhen.name )})ProvideTest({yuanZhen:this.yuan.yuanZhen})}}
}
运行:
点击父
点击子
点击父组件,输出:
由此可见,当class为嵌套类型时,父组件的UI不会改变,但是数据会改变,子组件的UI和数据都会改变
3,数组对象的使用
子组件
import Yuan from './bean/Yuan'@Component
export default struct ProvideTest {@ObjectLink yuan:Yuanbuild() {Row() {Column() {Text("子name:"+this.yuan.yuanZhen.name+"\nage:"+this.yuan.yuanZhen.age+"\nnumber:"+this.yuan.number).fontSize(50).fontWeight(FontWeight.Bold).onClick(() => {this.yuan.yuanZhen.name ="袁震子组件"this.yuan.yuanZhen.age=35console.log("yz---name:"+this.yuan.yuanZhen.name)})}.width('100%')}.height('100%')}
}
父组件
import Yuan from './bean/Yuan';
import YuanZhen from './bean/YuanZhen';
import ProvideTest from './ProvideTest';@Entry
@Component
struct Index {@State yuan:Array<Yuan>=new ArrayaboutToAppear(){let yuan1:Yuan =new Yuan(1,new YuanZhen("袁震1",18))let yuan2:Yuan =new Yuan(2,new YuanZhen("袁震2",19))let yuan3:Yuan =new Yuan(3,new YuanZhen("袁震3",20))this.yuan.push(yuan1)this.yuan.push(yuan2)this.yuan.push(yuan3)}build() {Column(){Text("父name:" + this.yuan[0].yuanZhen.name+"\nage:"+this.yuan[0].yuanZhen.age+"\nnumber:"+this.yuan[0].number).fontSize(50).fontWeight(FontWeight.Bold).onClick(() => {this.yuan[0].yuanZhen.name="袁震父组件"this.yuan[0].number =10this.yuan[0].yuanZhen.age=30})ProvideTest({yuan:this.yuan[0]})}}}
运行:
点击父
点击子
可以看到,父组件不会更新本身的UI,会更新子组件的UI,子组件既不会更新自己的UI也不会更新父组件的UI。
但是,可以直接传给子组件简单类,这样可以更新子组件
子组件
import YuanZhen from './bean/YuanZhen'@Component
export default struct ProvideTest {@ObjectLink yuanZhen:YuanZhenbuild() {Row() {Column() {Text("子name:"+this.yuanZhen.name+"\nage:"+this.yuanZhen.age).fontSize(50).fontWeight(FontWeight.Bold).onClick(() => {this.yuanZhen.name ="袁震子组件"this.yuanZhen.age=35console.log("yz---name:"+this.yuanZhen.name)})}.width('100%')}.height('100%')}
}
父组件
import Yuan from './bean/Yuan';
import YuanZhen from './bean/YuanZhen';
import ProvideTest from './ProvideTest';@Entry
@Component
struct Index {@State yuan:Array<Yuan>=new ArrayaboutToAppear(){let yuan1:Yuan =new Yuan(1,new YuanZhen("袁震1",18))let yuan2:Yuan =new Yuan(2,new YuanZhen("袁震2",19))let yuan3:Yuan =new Yuan(3,new YuanZhen("袁震3",20))this.yuan.push(yuan1)this.yuan.push(yuan2)this.yuan.push(yuan3)}build() {Column(){Text("父name:" + this.yuan[0].yuanZhen.name+"\nage:"+this.yuan[0].yuanZhen.age+"\nnumber:"+this.yuan[0].number).fontSize(50).fontWeight(FontWeight.Bold).onClick(() => {this.yuan[0].yuanZhen.name="袁震父组件"this.yuan[0].number =10this.yuan[0].yuanZhen.age=30})ProvideTest({yuanZhen:this.yuan[0].yuanZhen})}}}
点击父
点击子
父组件的ui不会改变,子组件的UI会实时更新
相关文章:
鸿蒙Harmony--状态管理器-@Observed装饰器和@ObjectLink装饰器详解
经历的越多,越喜欢简单的生活,干净的东西,清楚的感觉,有结果的事,和说到做到的人。把圈子变小,把语放缓,把心放宽,用心做好手边的事儿,该有的总会有的! 目录 一ÿ…...
pytorch安装
pytoch安装 1. 准备工作1.1 需要提前安装的软件 2. 安装pyTorch我遇到的问题 3. 显卡测试4. CPU与GPU切换方法4.1 创建张量4.2 第一种切换方法4.3 第二种切换方法 1. 准备工作 1.1 需要提前安装的软件 Anaconda 史上最全最详细的Anaconda安装教程CUDA CUDA安装教程࿰…...
GBASE南大通用系统目录表
系统目录由描述数据库结构的表和视图组成。这些表对象有时称为数据字典,它们包含 数据库本身的所有信息。每个系统目录表都包含有关数据库中特定元素的信息。每个数据 库都有它自己的系统目录。 这些主题提供了有关系统目录表的结构、内容和使用的信息。还包含了有关…...
RPCMS跨站脚本漏洞(xss)
CNVD-ID: CNVD-2024-01190 漏洞描述: RPCMS是一个应用软件,一个网站CMS系统。 RPCMS v3.5.5版本存在跨站脚本漏洞,该漏洞源于组件/logs/dopost.html中对用户提供的数据缺乏有效过滤与转义,攻击者可利用该漏洞通过注入精心设计的有效载荷执行…...
Linux进阶命令使用
在 Linux 中,除了常用的基础命令,有一系列进阶命令可以帮助用户更有效地管理系统和执行复杂的任务。以下是一些常见的 Linux 进阶命令及其用法: 文本处理 grep:搜索文本并打印匹配的行。 grep pattern filenameawk:用…...
重定位,进程的创建,线程相关
重定位 进程的重定位指将程序加载到内存中不同的位置执行,在进程换出换入过程中将会发生。通过更新程序中使用的相对地址。 进程的创建——fork() 进程树,在自己的节点下创建进程节点。 使用fork,创建的子进程是父进…...
Java填充Execl模板并返回前端下载
功能:后端使用Java POI填充Execl模板,并返回前端下载 Execl模板如下: 1. Java后端 功能:填充模板EXECL,并返回前端 controller层 package org.huan.controller;import org.huan.dto.ExcelData; import org.huan.util.ExcelT…...
ChatGPT本地部署,学习记录
一、GPT4ALL模型 官网地址: Github:https://github.com/nomic-ai/gpt4all GPT4ALL项目部署简易,但是在运行体验上一般,并且是只调用CPU来进行运算。 看官方文档介绍在嵌入式上有比较大的优势,但是目前个人对嵌入式…...
Find My游戏手柄|苹果Find My技术与手柄结合,智能防丢,全球定位
游戏手柄是一种常见电子游戏机的部件,通过操纵其按钮等,实现对游戏虚拟角色的控制。随着游戏设备硬件的升级换代,现代游戏手柄又增加了:类比摇杆(方向及视角),扳机键以及HOME菜单键等。现在的游…...
2024美赛数学建模思路 - 复盘:光照强度计算的优化模型
文章目录 0 赛题思路1 问题要求2 假设约定3 符号约定4 建立模型5 模型求解6 实现代码 建模资料 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 问题要求 现在已知一个教室长为15米,宽为12米&…...
【Deep Dive: AI Webinar】开放 ChatGPT - 人工智能开放性运作的案例研究
【深入探讨人工智能】网络研讨系列总共有 17 个视频。我们按照视频内容,大致上分成了 3 个大类: 1. 人工智能的开放、风险与挑战(4 篇) 2. 人工智能的治理(总共 12 篇),其中分成了几个子类&…...
Devops相关问题及答案(2024)
1、DevOps 的理念是什么? DevOps是一种组织文化、流程和工具的集合,旨在提高软件交付的速度和质量,通过自动化和持续改进的方法来促进开发(Dev)和运维(Ops)的协作。 DevOps的核心理念包括&…...
掌握Python设计模式,SQL Alchemy打破ORM与模型类的束缚
大家好,反转软件组件之间的依赖关系之所以重要,是因为它有助于降低耦合度和提高模块化程度,进而可以提高软件的可维护性、可扩展性和可测试性。 当组件之间紧密耦合时,对一个组件的更改可能会对其他组件产生意想不到的影响&#…...
性能分析与调优: Linux 磁盘I/O 观测工具
目录 一、实验 1.环境 2.iostat 3.sar 4.pidstat 5.perf 6. biolatency 7. biosnoop 8.iotop、biotop 9.blktrace 10.bpftrace 11.smartctl 二、问题 1.如何查看PSI数据 2.iotop如何安装 3.smartctl如何使用 一、实验 1.环境 (1)主机 …...
Could not erase files or folders:
IDEA删除 git 的 localChanges 内的文件时,提示Could not erase files or folders:。 确认下这个文件是否被打开,忘记关闭了;关闭后可以被删除。(文件被打开的情况下,用操作系统自带的删除,也无法删除成功…...
算法训练营第四十四天|动态规划:完全背包理论基础 518.零钱兑换II 377. 组合总和 Ⅳ
目录 动态规划:完全背包理论基础Leetcode518.零钱兑换IILeetcode377. 组合总和 Ⅳ 动态规划:完全背包理论基础 文章链接:代码随想录 题目链接:卡码网:52. 携带研究材料 思路:完全背包问题,物品可…...
探索计算机网络:应用层的魅力
在当今数字化时代,计算机网络已成为我们生活和工作中不可或缺的一部分。网络的每一层都扮演着独特而重要的角色,而应用层,作为网络模型中用户最直接接触的部分,其重要性不言而喻。这篇文章旨在深入探索应用层的核心概念、功能以及…...
MySQL 按日期流水号 条码 分布式流水号
有这样一个场景,有多台终端,要获取唯一的流水号,流水号格式是 日期0001形式,使用MySQL的存储过程全局锁实现这个需求。 以下是代码示例。 注:所有的终端连接到MySQL服务器获取流水号,如果获取到的是 “-1”…...
前端导出Excel文件,部分数字前面0消失处理办法
详细导出可以看之前的文章 js实现导出Excel文档_js 通过 接口 导出 xlsx 代码-CSDN博客 今天的问题是导出一些数据时,有些字段是前面带有0的字符串,而导出后再excel中就被识别成了数字 如图本来字符串前面的0 都没了 解决方案 1. 导出的时候在前面加单…...
零基础学Python网络爬虫案例实战 全流程详解 高级进阶篇
零基础学Python网络爬虫案例实战 全流程详解 入门与提高篇 零基础学Python网络爬虫案例实战 全流程详解 高级进阶篇 编辑推荐 本书讲解了Python爬虫技术的高级进阶知识,帮助有一定爬虫基础的读者进一步提高爬虫技术。本书详解了突破反爬机制的常用手段以及Scrapy和…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
