【HarmonyOS】深入理解@Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化

news2024/9/22 13:18:49

【HarmonyOS】深入理解@Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化

前言

之前就Observed和ObjectLink写过一篇讲解博客【HarmonyOS】 多层嵌套对象通过@ObjectLink和@Observed实现渲染更新处理!

其中就@Observe监听类的使用,@ObjectLink进行数据传递进行了讲解。但是其中有些细节没有展开讲,对使用可能会有误解,所以新增一篇详细讲述。

特性明确

对于@ObjectLink和@Observed,我们一般理解为对嵌套对象进行属性监听的一组状态管理标签。
该组标签的诞生是为了解决嵌套对象or数组套数组,数组套对象等等,这种类似数据结构的监听问题,以便于ArkUI框架监听,来实现数据变化,UI渲染。

但是我们使用时,需要明确其作用范围,这样就可以避免一些奇怪的bug。

使用@ObjectLink和@Observed只能监听嵌套后的一级对象属性以及基类属性,无法监听子级及其以下的对象属性。

该结论以我上一篇博客举例,可以点击跳转到该博客,将DEMO示例代码copy下来,边看讲解,边操作DEMO效果更容易理解。

在列表操作数据变化时,我们即操作了一级属性,也操作了二级和三级属性,进行了数值修改。

if判断包裹的select属性为@ObjuectLink直接监听的对象一级属性,如果我们操作了该属性数值变化,就会导致UI刷新。所以if语句块下方的index和content内容变化也能刷新到UI。

该效果可参见前三个Item,点击后就无效果。只有后三个点击后才会有UI刷新。
在这里插入图片描述
如此情况如何解决呢?其实嵌套深层次数据结构监听问题,已反馈给华为官方。他们还在开发中,目前V2接口已经可实现嵌套深层次的监听问题。

@ObservedV2装饰器和@Trace装饰器:类属性变化观测,但是新的状态管理标签,还未开发完成,目前不推荐使用,因为不是最终版,随时会变化。

目前该问题的解决方案是:

1.进行二次拆分,继续往下监听对象,这样就可以实现多层数据监听。

但是如果嵌套层数过多,每一层都这样拆分,太过去繁琐。所以我推荐第二种方式,即:

2.对监听层的属性对象,进行操作赋值,不对属性对象之下的属性进行单独赋值。

以我上一篇demo示例代码举例:
在这里插入图片描述
当然了,还有一种最简单的方式就是,每次你改变嵌套数据时,监听层有属性也会变化,那UI就会及时刷新。如我DEMO示例一样,正常情况下,我们的Select属性是一定会改变,那UI就会及时刷新。

DEMO示例

以下DEMO示例验证过程【使用@ObjectLink和@Observed只能监听嵌套后的一级对象属性以及基类属性,无法监听子级及其以下的对象属性】

在这里插入图片描述

import { ButtonModifier, TextModifier } from '@ohos.arkui.modifier';

let NextID: number = 1;


class Bag {
  public id: number;
  public size: number;

  constructor(size: number) {
    this.id = NextID++;
    this.size = size;
  }
}


class BagCopy {
  public id: number;
  public size: number;

  constructor(size: number) {
    this.id = NextID++;
    this.size = size;
  }
}


class Cup {
  public id: number;
  public size: number;

  constructor(size: number) {
    this.id = NextID++;
    this.size = size;
  }
}


class User {
  public bag: Bag;

  constructor(bag: Bag) {
    this.bag = bag;
  }
}


class Book {
  public bookName: BookName;

  constructor(bookName: BookName) {
    this.bookName = bookName;
  }
}


class BookName extends BagCopy {
  public nameSize: number;
  public cup: Cup;

  constructor(nameSize: number) {
    // 调用父类方法对nameSize进行处理
    super(nameSize);
    this.nameSize = nameSize;
    this.cup = new Cup(nameSize);
  }
}


struct ViewA {
  label: string = 'ViewA';
   bag: Bag;

  private mTextCommonStyle = new TextCommonStyle();
  private mButtonCommonStyle = new ButtonCommonStyle();

  build() {
    Column() {
      Text(`ViewA`)
        .attributeModifier(this.mTextCommonStyle)

      Text(`this.bag.size = ${this.bag.size}`)
        .attributeModifier(this.mTextCommonStyle)

      Button(`click this.bag.size add 1`)
        .attributeModifier(this.mButtonCommonStyle)
        .onClick(() => {
          this.bag.size += 1;
        })
    }
    .backgroundColor(Color.Blue)
  }
}


struct ViewC {
  label: string = 'ViewC1';
   bookName: BookName;

  private mTextCommonStyle = new TextCommonStyle();
  private mButtonCommonStyle = new ButtonCommonStyle();

  build() {
    Row() {
      Column() {
        Text(`ViewC`)
          .attributeModifier(this.mTextCommonStyle)

        Text(`this.bookName.cup.size = ${this.bookName.cup.size}`)
          .attributeModifier(this.mTextCommonStyle)

        Button(`click this.bookName.cup.size add 1`)
          .attributeModifier(this.mButtonCommonStyle)
          .onClick(() => {
            // 当前监听对象的属性,如果是嵌套对象,则该嵌套对象的属性赋值,不会被框架监听到,UI不刷新
            this.bookName.cup.size += 1;
            console.log('this.bookName.size:' + this.bookName.size)
          })

        Divider().height(5)

        Text(`this.bookName.size = ${this.bookName.size}`)
          .attributeModifier(this.mTextCommonStyle)

        Button(`click this.bookName.size add 1`)
          .attributeModifier(this.mButtonCommonStyle)
          .onClick(() => {
            // 当前监听对象的基类属性被修改,依旧可以被监听到,UI会刷新
            this.bookName.size += 1;
            console.log('this.bookName.size:' + this.bookName.size)
          })

      }
      .width(320)
      .backgroundColor(Color.Red)
    }
  }
}

class TextCommonStyle implements AttributeModifier<TextModifier> {
  applyNormalAttribute(instance: TextModifier): void {
    instance
      .fontColor('#ffffffff')
      .backgroundColor('#ff3d9dba')
      .width(320)
      .height(50)
      .borderRadius(25)
      .margin(10)
      .textAlign(TextAlign.Center)
  }
}

class ButtonCommonStyle implements AttributeModifier<ButtonModifier> {
  applyNormalAttribute(instance: ButtonModifier): void {
    instance
      .width(320)
      .backgroundColor('#ff17a98d')
      .margin(10)
  }
}




struct ViewB {
   user: User = new User(new Bag(0));
   child: Book = new Book(new BookName(0));

  build() {
    Scroll(){
      Column() {
        ViewA({ bag: this.user.bag })
          .width(320)
        ViewC({ bookName: this.child.bookName })
          .width(320)
        Button(`ViewB: this.child.bookName.size add 10`)
          .width(320)
          .backgroundColor('#ff17a98d')
          .margin(10)
          .onClick(() => {
            this.child.bookName.size += 10
            console.log('this.child.bookName.size:' + this.child.bookName.size)
          })
        Button(`ViewB: this.user.bag = new Bag(10)`)
          .width(320)
          .backgroundColor('#ff17a98d')
          .margin(10)
          .onClick(() => {
            this.user.bag = new Bag(10);
          })
        Button(`ViewB: this.user = new User(new Bag(20))`)
          .width(320)
          .backgroundColor('#ff17a98d')
          .margin(10)
          .onClick(() => {
            this.user = new User(new Bag(20));
          })
      }
    }
  }
}

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

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

相关文章

prometheus监控linux虚拟机

前提条件已安装好prometheus和grafana&#xff0c;如果未安装请移步到docker部署prometheus 安装部署Prometheus,docker安装grafana安装部署Grafana。 1.二进制部署node-exporter采集器 2.1 采集器node-exporter下载 链接&#xff1a;https://pan.baidu.com/s/1hDmckSSl5X36…

【算法】BFS系列之 拓扑排序

【ps】本篇有 3 道 leetcode OJ。 目录 一、算法简介 二、相关例题 1&#xff09;课程表 .1- 题目解析 .2- 代码编写 2&#xff09;课程表 II .1- 题目解析 .2- 代码编写 3&#xff09;火星词典 .1- 题目解析 .2- 代码编写 一、算法简介 【补】图的基本概念 &#…

本地提权【笔记总结】

文章目录 服务命令at命令提权介绍适用版本复现 sc命令提权介绍适用版本复现 ps应用程序提权复现 进程注入进程迁移注入介绍条件复现 MSF自动化注入介绍getsystem原理 复现 MSF令牌窃取介绍复现 烂土豆提权介绍适用版本复现 UAC绕过介绍复现使用ask模块绕过使用bypassuac_sluihi…

谷歌的AI反击战:创始人谢尔盖·布林的回归与大模型组合的未来

近年来&#xff0c;随着AI技术的迅猛发展&#xff0c;尤其是ChatGPT等大语言模型的出现&#xff0c;全球科技格局正发生剧烈变化。作为曾经引领AI潮流的谷歌&#xff0c;在这场竞争中逐渐失去了领头羊的地位。然而&#xff0c;谷歌的创始人之一谢尔盖布林&#xff08;Sergey Br…

计算组合数

1.递推 #include<bits/stdc.h> #include<unordered_map> #include<unordered_set> using namespace std; #define int long long //可能会超时 #define PII pair<int,int> const int INF 0x3f3f3f3f, mod 1e9 7; const int N 2005; int a, b,n; …

手机自动化测试环境之夜神模拟器inspector部署验证

1、自动化测试环境部署_总览图检查表流程图 Python需要安装Appium-Python-Clicent去定位元素&#xff1b;Appium是一个中间的服务器&#xff0c;它需要依赖node.js&#xff0c;python的脚本通过appium和手机进行交互&#xff1b;手机app的环境都是java环境&#xff0c;先安装jd…

9、等保测评介绍

数据来源&#xff1a;9.等保测评介绍_哔哩哔哩_bilibili 信息系统等级测评 信息系统等级测评是测评机构依据国家信息安全等级保护制度的规定&#xff0c;按照相关管理规范和技术标准&#xff0c;对未涉及国家秘密的信息系统的安全等级保护状况进行检测评估的活动。 等级测评…

gitlab 的CI/CD (一)

前言 GitLab CI/CD 是一个内置在GitLab中的工具&#xff0c;用于通过持续方法进行软件开发&#xff1a; Continuous Integration (CI) 持续集成Continuous Delivery (CD) 持续交付Continuous Deployment (CD) 持续部署 持续集成的工作原理是将小的代码块推送到Git仓库…

JavaEE: 深入探索TCP网络编程的奇妙世界(三)

文章目录 TCP核心机制TCP核心机制三: 连接管理建立连接(三次握手)断开连接(四次挥手)三次握手/四次挥手 流程简图 TCP核心机制 书接上文~ TCP核心机制三: 连接管理 建立连接(三次握手),断开连接(四次挥手). 这里的次数指的是网络通信的次数,挥手/握手是形象的比喻(handshake…

PM2.5粉尘传感器详解(STM32)

目录 一、介绍 二、传感器原理 1.原理图 2.引脚描述 3.工作原理介绍 4.粉尘浓度转化关系 5.空气污染指数 三、程序设计 main.c文件 PM25.h文件 PM25.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 GP2Y1014AU是日本夏普公司开发的一款光学灰尘浓度检测传…

探索 Web Speech API:实现浏览器语音识别与合成

引言 Web Speech API 是一项由 W3C 开发的 Web 标准&#xff0c;为开发者提供了在 Web 应用程序中实现语音识别和语音合成的能力。通过 Web Speech API&#xff0c;我们可以让网页与用户进行语音交互&#xff0c;实现更加智能化和便捷的用户体验。本文将深入探讨 Web Speech A…

14 vue3之内置组件trastion全系列

前置知识 Vue 提供了 transition 的封装组件&#xff0c;在下列情形中&#xff0c;可以给任何元素和组件添加进入/离开过渡: 条件渲染 (使用 v-if)条件展示 (使用 v-show)动态组件组件根节点 自定义 transition 过度效果&#xff0c;你需要对transition组件的name属性自定义。…

【Linux】当前进展

驱动层日志添加了下文件目录&#xff0c;函数&#xff0c;代码行的打印&#xff08;这里要小心&#xff0c;驱动目录源代码打印日志里边添进程号可能有问题&#xff0c;因为在驱动初始化的时候&#xff0c;内核还没有创建进程&#xff0c;不过猜测可以先不打印进程相关信息&…

python使用vscode 所需插件

1、导读 环境&#xff1a;Windows 11、python 3.12.3、Django 4.2.11、 APScheduler 3.10.4 背景&#xff1a;换系统需要重新安装&#xff0c;避免后期忘记&#xff0c;此处记录一下啊 事件&#xff1a;20240921 说明&#xff1a;记录&#xff0c;方便后期自己查找 2、插件…

Ansys Zemax | 如何使用琼斯矩阵表面

附件下载 联系工作人员获取附件 概览 琼斯矩阵 (Jones Matrix) 表面是一种非常简便的定义偏振元件的方法。这篇文章通过几个示例介绍了如何使用琼斯矩阵。 介绍 光线追迹程序一般只考虑光线的几何属性&#xff08;位置、方向和相位&#xff09;。光线传播到一个表面时的全…

SQL - 进阶语法(二)约束

1. SQL约束 约束用于约束表中的数据规则&#xff0c;如若存在违反行为&#xff0c;行为会被约束终止。 • NOT NULL 确保列不能有NULL值 如果添加一行新的数据&#xff0c;不能有null值&#xff0c;否则无法添加 新建表格 CREATE TABLE new_table( ID int NOT NULL, NAME …

梯形区域分解实现避障路径规划全覆盖路径规划

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言&#xff08;1&#xff09;功能&#xff08;2&#xff09;算法&#xff08;3&#xff09;参考链接&#xff08;4&#xff09;…

【服务器第二期】mobaxterm软件下载及连接

【服务器第二期】mobaxterm软件下载及连接 前言什么是SSH什么是FTP/SFTP mobaxterm软件介绍mobaxterm软件下载SSH登录使用方法1-新建ssh连接方法2-打开已有的ssh连接方法3-通过ssh命令建立连接 SFTP数据传输方法1-建立ssh连接后直接拖拽方法2-建立sftp连接再拖拽方法3-直接使用…

Nacos配置管理(2)-----配置热更新

有很多的业务相关参数&#xff0c;将来可能会根据实际情况临时调整。例如购物车业务&#xff0c;购物车数量有一个上限&#xff0c;默认是10&#xff0c;对应代码如下&#xff1a; 现在这里购物车是写死的固定值&#xff0c;我们应该将其配置在配置文件中&#xff0c;方便后期…

while(cin>>a)

while(cin>>a)要结束输入CTRLZ换行 输入先调用&#xff1a; istream& operator>> (istream& is, string& str); 但返回值类型时istream&#xff0c; 再调用&#xff1a; 重载的原为(bool)istream&#xff0c;返回值为bool,重载的为括号&#xff0c…