鸿蒙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 = name
    this.age = age
  }
}

子组件

import YuanZhen from './bean/YuanZhen'

@Component
export default struct ProvideTest {

  @ObjectLink yuanZhen:YuanZhen

  build() {
    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 = name
    this.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 = number
    this.yuanZhen = yuanZhen
  }
}

子组件:

import YuanZhen from './bean/YuanZhen'

@Component
export default struct ProvideTest {

  @ObjectLink yuanZhen:YuanZhen

  build() {
    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 =20
          console.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:Yuan

  build() {
    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=35
            console.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 Array

  aboutToAppear(){
    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 =10
          this.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:YuanZhen

  build() {
    Row() {
      Column() {
        Text("子name:"+this.yuanZhen.name+"\nage:"+this.yuanZhen.age)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .onClick(() => {
            this.yuanZhen.name ="袁震子组件"
            this.yuanZhen.age=35
            console.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 Array

  aboutToAppear(){
    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 =10
          this.yuan[0].yuanZhen.age=30
        })
      ProvideTest({yuanZhen:this.yuan[0].yuanZhen})
    }
  }

}

点击父点击子

父组件的ui不会改变,子组件的UI会实时更新

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【壹基金儿童服务站瑞金站】寿司DIY亲子活动火热进行

1月13日下午&#xff0c;“大灰狼来啦....”在小朋友们一声声欢快律动的游戏里在象湖新城小区拉开了一场“寿司DIY”亲子主题活动序幕&#xff0c;活动由壹基金儿童服务站瑞金站&#xff08;瑞金赋能公益&#xff09;和爱心商家安心妈妈飞鹤奶粉联合主办。 热身游戏结束后&…

链接全域直播产业经济,天府锋巢直播产业基地10层正式起航

100㎡-400㎡多种类型的办公户型可选 精装全包 拎包入驻 【天府锋巢直播基地】 由德商产投与无锋科技联袂打造 坐落于天府新区核心区域科学城板块 包含电商直播、娱乐直播、跨境直播 多种直播业态的全域直播基地 基地【10层】于12月初全面竣工 招&#xff5c;商 &#xff5c;火&…

Jan, 一个开源 ChatGPT 替代品

Jan 是一个开源 ChatGPT 替代品&#xff0c;可以在您的计算机上 100% 离线运行。 Jan 可以在任何硬件上运行。从 PC 到多 GPU 集群&#xff0c;Jan 支持通用架构&#xff1a; Nvidia GPU&#xff08;快速&#xff09;Apple M 系列&#xff08;快速&#xff09;苹果英特尔Linu…

LLM之RAG实战(十五)| RAG的自动源引文验证技术

​ 在过去的一年里&#xff0c;检索增强生成&#xff08;RAG&#xff09;已经成为一种基于LLM的流行架构&#xff0c;旨在解决在基于知识的LLM最常见的挑战之一&#xff0c;可怕的幻觉。 一、RAG如何解决幻觉&#xff1f; RAG Pipeline包括两个关键组件&#xff1a;&…

基于Java SSM框架实现摄影器材租赁系统项目【项目源码+论文说明】

基于java的SSM框架实现摄影器材租赁系统演示 摘要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&a…

Linux(Centos7)安装 jenkins(jdk11+jenkins2.375),并配置JDK,Maven,Git,GitLab

安装步骤 1. JDK11安装2. Maven安装3. git安装4. Jenkins2.375安装4.1 设置中文显示4.2 端口,用户权限修改4.3 插件下载4.4 全局工具配置4.4.1 Maven配置4.4.2 JDK配置4.4.3 Git配置 4.5 系统配置4.5.1 Gitee配置 4.6 构建测试 1. JDK11安装 #下载 yum -y install fontconfig …

怎样获取power shell 的全部可用命令?2/5(篇幅有点长,分成5份)

在power shell 窗口中&#xff0c;有一个获取全部可用命令的命令&#xff1a;get-command&#xff0c;获取到的命令有1640多个&#xff0c;够学习了吧&#xff1f;那么&#xff0c;power shell 命令有哪些类别呢&#xff1f; PowerShell命令可以分为以下几类&#xff1a; Cmdl…

高可用架构去中心化重要?

1 背景 在互联网高可用架构设计中&#xff0c;应该避免将所有的控制权都集中到一个中心服务&#xff0c;即便这个中心服务是多副本模式。 对某个中心服务&#xff08;组件&#xff09;的过渡强依赖&#xff0c;那等同于把命脉掌握在依赖方手里&#xff0c;依赖方的任何问题都可…

开启C++之旅(上):探索命名空间与函数特性(缺省参数和函数重载)

之前浅显的讲解了数据结构的部分内容&#xff1a;数据结构专栏 那么今天我们迎来了新的起点&#xff1a;C的探索之旅 文章目录 1.命名空间1.1引入命名冲突1.2命名空间1.2.1命名空间的定义1.2.2命名空间的使用 2.c的输入与输出3.缺省参数3.1概念3.2缺省参数分类 4.函数重载4.1概…

【深基9.例4】求第 k 小的数#洛谷(MLE)

题目描述 输入 n n n&#xff08; 1 ≤ n < 5000000 1 \le n < 5000000 1≤n<5000000 且 n n n 为奇数&#xff09;个数字 a i a_i ai​&#xff08; 1 ≤ a i < 10 9 1 \le a_i < {10}^9 1≤ai​<109&#xff09;&#xff0c;输出这些数字的第 k k k 小…

吉祥物如何解锁虚拟主持人身份,赋能品牌营销?

在互联网突破时空的整体语境下&#xff0c;一个吉祥物可以解锁虚拟主持人身份&#xff0c;结合动作捕捉技术&#xff0c;活跃于品牌线上线下营销活动场景&#xff0c;让吉祥物虚拟主持人凭借其“萌”、的特征&#xff0c;带给用户亲近感&#xff0c;快速拉近品牌与用户的距离&a…

基于Web的航空航天数字博物馆推荐系统

介绍 项目背景&#xff1a; 航空航天数字博物馆推荐系统是一个基于Web开发的应用&#xff0c;旨在为用户提供一个全面的航空航天领域的数字博物馆体验。通过展品展示、分类筛选和个性化推荐等功能&#xff0c;用户可以更好地了解航空航天知识和文化&#xff0c;并丰富参观体验…

关于git删除仓库中原本应该忽略的文件的研究

开门见山&#xff0c;先抛出一个结论&#xff1a; 任何被提交到远程仓库中的数据&#xff0c;都不能被彻底删除&#xff0c;只要提交上去了&#xff0c;就会永远留存。 任何被提交到远程仓库中的数据&#xff0c;都不能被彻底删除&#xff0c;只要提交上去了&#xff0c;就会…

centos7 arm服务器编译安装gcc 8.2

前言 当前电脑的gcc版本为4.8.5&#xff0c;但是在编译其他依赖包的时候&#xff0c;出现各种奇怪的问题&#xff0c;会莫名其妙的中断编译。本地文章讲解如何自编译安装gcc&#xff0c;替换系统自带的gcc。 环境准备 gcc 需要 8.2&#xff1a;下载地址 开始编译 1、解压gcc…

服务器 conda update 失败解决方法

1. 强制 conda update 租借一台服务器&#xff0c;发现 conda 版本是4.10.3&#xff0c;需要升级&#xff0c;使用了如下命令都没有效果&#xff0c;仍然是一样的版本 conda update conda update --all conda update -n base -c defaults conda最后强制用conda-forge通道更新…

基于Java SSM框架实现学生成绩管理系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现学生成绩管理系统演示 摘要 学生成绩是高校人才培养计划的重要组成部分&#xff0c;是实现人才培养目标、培养学生科研能力与创新思维、检验学生综合素质与实践能力的重要手段与综合性实践教学环节。而学生所在学院多采用半手工管理学生成绩的方式&#…

linux命令太多记不住吗?怎么办 ?于是推出了这样一套教程。

1.帮助命令 1.1 help命令 #语法格式&#xff1a; 命令 --help #作用: 查看某个命令的帮助信息 # 示例: # ls --help 查看ls命令的帮助信息# netstat --help 查看netstat命令的帮助信息1.2 man命令 #语法格式&#xff1a; man 命令 #作用: 查看某个命令的帮助手册 # 示例: …

Codeforces Round 918 (Div. 4)补题

Odd One Out&#xff08;Problem - A - Codeforces&#xff09; 题目大意&#xff1a;有三个数&#xff0c;其中两个相同&#xff0c;找出不同的那个数。 #include<bits/stdc.h> using namespace std; int main() {int t;scanf("%d",&t);while(t--){vect…

电脑安装 Python提示“api-ms-win-crt-process-l1-1-0.dll文件丢失,程序无法启动”,快速修复方法,完美解决

在windows 10系统安装完python后&#xff0c;启动的时候&#xff0c;Windows会弹出错误提示框“无法启动此程序&#xff0c;因为计算机中丢失了api-ms-win-crt-process-l1-1-0.dll&#xff0c;尝试重新安装该程序以解决此问题。” api-ms-win-crt-process-l1-1-0.dll是一个动态…

TEMU、亚马逊、shein平台崛起迅猛,掌握自养号测评必备运营攻略

2023年12月&#xff0c;SimilarWeb发布的数据显示&#xff0c;TEMU的独立访客数量达到4.67亿&#xff0c;与Aliexpress持平&#xff0c;全球排名第二。亚马逊以26.59亿用户位居第一&#xff0c;而SHEIN则拥有1.723亿用户&#xff0c;排名第三。 然而&#xff0c;仅仅六个月前的…