鸿蒙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会实时更新

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

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

相关文章

SQL-DQL-基础查询

目录 DQL-介绍 DQL-语法 DQL-基本查询 &#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;重拾MySQL &#x1f4dc;其他专栏&#xff1…

python统计分析——小提琴图(plt.violinplot)

参考资料&#xff1a;用python动手学统计学&#xff0c;帮助文档 使用matplotlib.pyplot.violinplot()函数绘制小提琴图 小提琴图是将数值型数据的核密度图与箱线图融合在一起&#xff0c;具体来说是用核密度估计的结果替换了箱子&#xff0c;而形成的一个形似小提琴的图形。 …

SQL SERVER 19安装 SQL Prompt 10.02版本

SQL Prompt最新版官网下载地址&#xff1a;https://download.red-gate.com/SQLPromptDownload.exe 下载完成后&#xff0c;断开网络&#xff0c;全部点下一步。 注册机会报毒&#xff0c;安装前请先关闭杀毒软件&#xff01; 下载好附件之后解压&#xff0c;打开SQLPrompt_7…

Qt优秀开源项目之二十一:遇见QSkinny,一个轻量级Qt UI库

目录 一.QSkinny简介 二.工作原理 三.编译 一.QSkinny简介 QSkinny库基于Qt Graphic View和Qt/Quick中少量的核心类。它提供了一组轻量级控件&#xff0c;可以在C或QML中使用这些控件。QSkinny默认是启用硬件加速的&#xff0c;非常适合嵌入式设备&#xff0c;目前已经应用于…

商城小程序(8.购物车页面)

目录 一、商品列表区域1、渲染购物车商品列表的标题区域2、渲染商品列表区域的基本结构3、为my-goods组件封装radio勾选状态4、为my-goods组件封装radio-change事件5、修改购物车中商品的选择状态6、为my-goods组件封装NumberBox7、为my-goods封装num-change事件8、修改购物车商…

基于JavaWeb+BS架构+SpringBoot+Vue电影订票系统系统的设计和实现

基于JavaWebBS架构SpringBootVue电影订票系统系统的设计和实现 文末获取源码Lun文目录前言主要技术系统设计功能截图订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 文末获取源码 Lun文目录 1 绪 论 3 1.1研究背景和意义 3 1.2拟解决的问题及特性 3 1.3论文的结构 …

生物信息学导论-北大-序列比对基础知识

最近重新捡起coursera上的课了&#xff0c;这次准备好好学&#xff0c;把考试考了。。因此顺便记录一下学习过程。 ref: https://www.coursera.org/learn/sheng-wu-xin-xi-xue/home Sequence Alignment 序列比对 生物学问题 biological question: how to determine the simi…

科技创新领航 ,安川运动控制器为工业自动化赋能助力

迈入工业4.0时代&#xff0c;工业自动化的不断发展&#xff0c;让高精度运动控制成为制造业高质量发展的重要技术手段。北京北成新控伺服技术有限公司作为一家集工业自动化产品销售、系统设计、开发、服务于一体的高新技术企业&#xff0c;其引进推出的运动控制产品一直以卓越的…

libcurl开源库的编译与使用全攻略

libcurl简介 libcurl 是一个广泛使用的、支持多种协议的、开源的客户端URL传输库&#xff0c;提供了许多用于数据传输的API&#xff0c;例如文件传输、FTP、HTTP、HTTPS、SMTP等。libcurl 的主要特点包括 支持多种协议&#xff1a;libcurl 支持多种协议&#xff0c;如 HTTP、F…

thinkphp美容SPA管理系统源码带文字安装教程

thinkphp美容SPA管理系统源码带文字安装教程 运行环境 服务器宝塔面板 PHP 7.0 Mysql 5.5及以上版本 Linux Centos7以上 基于thinkphp3.23B-JUI1.2开发&#xff0c;权限运用了Auth类认证&#xff0c;权限可以细分到每个功能&#xff0c; 增删改查功能一应俱全&#xff0c;整合了…

基于YOLOv5的道路标志识别项目(yolov5界面GUI)

基于YOLOv5的道路标志识别项目&#xff08;yolov5界面GUI&#xff09; English | 简体中文 这是一个关于yolov5的道路标志识别项目&#xff0c;使用Pyqt5开发界面&#xff0c;Yolov5训练模型&#xff0c;数据库Mysql&#xff0c;包含五个模块&#xff1a;初始化参数、标志识别…

vim基本操作命令

一、vi简介 vi是“Visual interface”的简称&#xff0c;它在Linux上的地位就仿佛Edit程序在DOS上一样。它可以执行输出、删除、查找、替换、块操作等众多文本操作&#xff0c;而且用户可以根据自己的需要对其进行定制。Vi不是一个排版程序&#xff0c;它不象Word或WPS那样可以…