鸿蒙HarmonyOS开发:@Observed装饰器和@ObjectLink装饰器:监听嵌套类对象属性变化

文章目录

      • 一、装饰器
      • 二、概述
      • 三、限制条件
      • 四、装饰器说明
      • 五、Toggle组件
        • 1、子组件
        • 2、接口
        • 3、ToggleType枚举
        • 4、事件
      • 六、示例演示
        • 1、代码
        • 2、效果

一、装饰器

  • @State装饰器:组件内状态
  • @Prop装饰器:父子单向同步
  • @Link装饰器:父子双向同步
  • @Provide装饰器和@Consume装饰器:与后代组件双向同步

上文所述的装饰器仅能观察到第一层的变化,但是在实际应用开发中,应用会根据开发需要,封装自己的数据模型。对于多层嵌套的情况,比如二维数组,或者数组项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实例,API11及以上支持继承Map、Set的class实例。
@ObjectLink的属性是可以改变的,但是变量的分配是不允许的,也就是说这个装饰器装饰变量是只读的,不能被改变。
被装饰变量的初始值不允许。

五、Toggle组件

组件提供勾选框样式、状态按钮样式及开关样式。

1、子组件

仅当ToggleType为Button时可包含子组件。

2、接口

Toggle(options: { type: ToggleType, isOn?: boolean })

  • 参数
参数名参数类型必填参数描述
typeToggleType开关的样式。
默认值:ToggleType.Switch。
isOnboolean开关是否打开,true:打开,false:关闭。
默认值:false
从API version 10开始,该参数支持$$双向绑定变量。
3、ToggleType枚举
名称描述
Checkbox提供单选框样式。
Button提供状态按钮样式,如果子组件有文本设置,则相应的文本内容会显示在按钮内部。
默认尺寸为:高为28vp,宽无默认值。
Switch提供开关样式。

在这里插入图片描述

4、事件

开关状态切换时触发该事件。

onChange(callback: (isOn: boolean) => void)

  • 参数
参数名类型必填说明
isOnboolean为true时,代表状态从关切换为开。false时,代表状态从开切换为关。

六、示例演示

本示例演示联系人管理功能页面。
可以新增,删除,收藏,展开手机号登功能。
使用到的组件间相互通信功能
@Prop装饰器:父子单向同步
@Link装饰器:父子双向同步
@Watch装饰器监听状态变量的变化
@Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化
@Extend装饰器:定义扩展组件样式
Toggle组件

1、代码
// 定义变量ID,默认从1开始,自增
let id = 1// @Observed装饰的类
@Observed
class Person {name: stringphone: stringisCollect: boolean = falseid: numberconstructor(name: string, phone: string) {// id自增this.id = id++this.name = namethis.phone = phone}
}// 随机姓名方法,为了演示简写
function getRandomName() {return "张三" + Math.floor(Math.random() * 100)
}//随机手机号,为了演示简写
function getRandomPhone() {return "1" + (Math.floor(Math.random() * 9000000000) + 1000000000)
}@Entry
@Component
struct ContactsList {// 联系人列表@State contactsList: Person[] = [new Person(getRandomName(), getRandomPhone()), new Person(getRandomName(), getRandomPhone())]// 当前展开的联系人ID@State currentExpandID: number = 0// 是否点击选中@State isSelect: boolean = false// 选中的联系人ID列表@State selectIdList: number[] = []build() {Column() {Row({ space: 10 }) {Text("联系人管理").fontSize(20)Blank()Button(this.isSelect ? "取消" : "选中")// 扩展组件样式.globalButtonStyle(Color.Gray)// 点击切换选中/取消按钮事件.onClick(() => {this.isSelect = !this.isSelectthis.selectIdList = []})Button("+")// 扩展组件样式.globalButtonStyle(Color.Gray).onClick(() => {// 新增联系人this.contactsList.push(new Person(getRandomName(), getRandomPhone()))})}.width("100%").padding(10)List({ space: 10 }) {ForEach(this.contactsList, (item: Person) => {ListItem() {// 观察对象类属性变化,要配合自定义组件使用ContactsItem({ item,currentExpandID: $currentExpandID,isSelect: this.isSelect,selectIdList: $selectIdList })}})}.padding(10).layoutWeight(1)if (this.isSelect) {Button("删除").margin(10)// 扩展组件样式.globalButtonStyle(Color.Red)// 删除按钮点击事件.onClick(() => {this.contactsList = this.contactsList.filter((item: Person) => {return !this.selectIdList.includes(item.id)})})}}.width('100%').height('100%').backgroundColor("#f7f7f7")}
}// 自定义组件
@Component
struct ContactsItem {// 数据双向同步,需要搭配@ObjectLink@ObjectLink item: Person// 组件内状态@State isExpand: boolean = false// 父子双向同步 监听状态变化@Link @Watch("onChangeCurrentID") currentExpandID: number// 父子单向同步@Prop isSelect: boolean// 父子双向同步@Link selectIdList: number[]// 监听状态变量变化回调onChangeCurrentID() {if (this.item.id != this.currentExpandID) {this.isExpand = false}}build() {Column() {Row({ space: 10 }) {// 复选框if (this.isSelect) {Toggle({ type: ToggleType.Checkbox })// 选中状态发生变化时的事件.onChange((val) => {if (val) {this.selectIdList.push(this.item.id)} else {let index: number = this.selectIdList.indexOf(this.item.id)this.selectIdList.splice(index, 1)}})}// 头像Image($r("app.media.picture")).width(30).height(30)// 姓名Text(this.item.name).fontSize(18)Blank()// 收藏Image(this.item.isCollect ? $r("app.media.collect_select") : $r("app.media.collect")).width(26).height(26).onClick(() => {// 第二层的属性值变化this.item.isCollect = !this.item.isCollect})}.height(40).width("100%")// 手机号if (this.isExpand) {Divider().margin({ top: 10, bottom: 6 }).color("#EEEEEE")Row() {Text("手机号码:" + this.item.phone).fontSize(16)}.height(30).width("100%")}}.width("100%").padding(10).borderRadius(6).backgroundColor(Color.White)// 点击展开显示手机号码.onClick(() => {this.isExpand = !this.isExpandthis.currentExpandID = this.item.id})}
}// 定义扩展组件样式
@Extend(Button) function globalButtonStyle(color: Color) {.height(30).fontSize(14).backgroundColor(color)
}
2、效果
  • 点击新增按钮,可以新增联系人
  • 点击收藏按钮,可以切换是否收藏
    在这里插入图片描述
  • 点击联系人,可以展开当前联系人,查看手机号码
  • 点击上面选择按钮,可以切换选择页面
  • 点击联系人前面复选框,可以选中联系
  • 点击删除按钮,可以删除选中的联系人
    在这里插入图片描述

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

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

相关文章

SpringBoot MybatisPlus selectOne的坑

目录 一、问题 二、问题解决 三、其他方法 一、问题 selectOne在查询多条数据时会报错,查询语句并不会加 limit 1。 One record is expected, but the query result is multiple records。 二、问题解决 在QueryWrapper上添加如下: QueryWrapper&…

支付宝开放平台竟出现一张神秘人脸!

前言 ​ 我因一个单子来到支付宝开放平台来。在将其加入书签的时候,我发现出现了个神秘的人脸 一张笑容明媚的脸,就是出现的时候不太对 正常的收藏网址 应该是显示对应log 就不继续找相关例子了 ​ 添加书签的页面,本该出现log的地方缺出现了…

VScode的环境编译器选择

按快捷键 Ctrl Shift P 选择即可

反向传播与梯度累积

反向传播算法:loss.backward()的实现细节 向前传播:输入数据得到预测结果。向后传播:计算梯度加更新参数。反向传播:计算梯度 计算图 计算图 有向无环图 基本运算 节点:变量节点 & 计算节点有向边&#xff1…

【LeetCode】48. 旋转图像

旋转图像 题目描述: 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1: 输入:matrix …

【维修经验分享】可调电源输出不稳定

一、前言 从今天这期开始,我将在“维修经验”这个专栏中分享一些简单的电路板维修经历,希望能帮助大家。 二、相关信息及问题 型号:迈胜MS-3050。 问题:输出电压无法稳定下来,一直在跳动。这款电源估计也比较老了&…

Linux系统之ls命令的基本使用

Linux系统之ls命令的基本使用 一、ls命令介绍二、ls命令的使用帮助2.1 命令格式2.2 命令选项2.3 使用帮助 三、ls命令的基本使用3.1 列出当前目录中的所有文件和目录3.2 列出指定目录中的所有文件和目录3.3 显示文件的详细信息3.4 列出所有文件和目录3.5 显示目录本身&#xff…

【单片机毕业设计选题24105】-基于单片机的自动配料机控制系统

系统功能: 系统分为自动状态和手动状态上电默认为手动状态,手动状态下可以通过按键和蓝牙手动控制步进电机正反转, 自动状态下根据采集到的两路接近传感器信号自动控制步进电机正反转。 系统上电后,OLED显示“欢迎使用请稍后”&#xff0c…

C++17常用新特性介绍

目录 1、结构化绑定 2、constexpr扩展 2.1、constexpr lambda 2.2、constexpr if 2.3、constexpr string 4、if with initializer 5、std::optional 6、使用inline定义内联变量 7、std::filesystem库 8、折叠表达式 9、模板的模板参数推导 9.1、从构造函数参数推导…

前端获取视频文件宽高信息和视频时长

安装 yarn add video-metadata-thumbnails | npm install video-metadata-thumbnails引入依赖包 import { getMetadata } from video-metadata-thumbnails使用 if (file.name.includes(mp4)) {if (file) {try {console.log(file)// 获取视频的元数据const metadata await …

【微信小程序开发】——奶茶点餐小程序的制作(一)

👨‍💻个人主页:开发者-曼亿点 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 曼亿点 原创 👨‍💻 收录于专栏&#xff1a…

51单片机—智能垃圾桶(定时器)

一. 定时器 1. 简介 C51中的定时器和计数器是同一个硬件电路支持的,通过寄存器配置不同,就可以将他当做定时器或者计数器使用。 确切的说,定时器和计数器区别是致使他们背后的计数存储器加1的信号不同。当配置为定时器使用时,每…

数据结构的基本概念

数据结构的基本概念 数据是什么? 数据 : 数据是信息的载体,是描述客观事物属性的数、字符及所有能输入到计算机中并被计算机程序识别(二进制0|1)和处理的符号的集合。数据是计算机程序加工的原料。 早期计算机处理的…

【代码随想录】有序数组的平方

本博文为《代码随想录》的学习笔记,原文链接:代码随想录 题目 977. 有序数组的平方 给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。 示例 1: 输入&…

【物联网设备端开发】使用QEMU模拟ESP硬件运行ESP-IDF

目录 一,开发环境搭建 1.1 安装ESP-IDF 1.2 安装vscode插件 1.3 在ESP-IDF插件配置ESP-IDF开发配置 1.4 下载IOTDeviceSDK 设备端开发代码 1.5 通过ESP-IDF插件编译好镜像 1.6 构建QEMU docker镜像 1.7 使用QEMU容器运行镜像 二,搭建QEMU环境步…

PTrade常见问题系列22

反馈定义的上午7点执行run_daily函数,但是每周一上午都没法正常执行? 1、run_daily函数加载在initialize函数中,执行后才会创建定时任务; 2、由于周末会有例行重启操作,在重启以后拉起交易时相当于非交易日启动的交易…

C到C++——C++基础

C是一种通用的、静态类型的、跨平台的编程语言。它是在1979年由Bjarne Stroustrup创建的,最初是作为C语言的扩展来支持面向对象编程。 C在保留C语言的特性的同时,添加了许多其他的功能,包括类、对象、继承、多态、模板等。这使得C成为了一种…

大数据面试SQL(五):查询最近一笔有效订单

文章目录 查询最近一笔有效订单 一、题目 二、分析 三、SQL实战 四、样例数据参考 查询最近一笔有效订单 一、题目 现有订单表t5_order,包含订单ID,订单时间,下单用户,当前订单是否有效。 请查询出每笔订单的上一笔有效订…

Vue - 关于vue-kinesis 移动动画组件

Vue - 关于vue-kinesis 移动动画组件 vue-kinesis可以根据鼠标移动或滚动条来控制元素动画的动画效果;除此之外,vue-kinesis 还可以设置音频文件,根据音频频率来控制动画的跳动效果。 一、安装vue-kinesis Vue2版本: 1.安装 …

2024.8.08(python)

一、搭建python环境 1、检查是否安装python [rootpython ~]# yum list installed | grep python [rootpython ~]# yum list | grep python3 2、安装python3 [rootpython ~]# yum -y install python3 安装3.12可以使用源码安装 3、查看版本信息 [rootpython ~]# python3 --vers…