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

news2024/9/9 0:26:30

文章目录

      • 一、装饰器
      • 二、概述
      • 三、限制条件
      • 四、装饰器说明
      • 五、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: string
  phone: string
  isCollect: boolean = false
  id: number

  constructor(name: string, phone: string) {
    // id自增
    this.id = id++
    this.name = name
    this.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.isSelect
            this.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.isExpand
      this.currentExpandID = this.item.id
    })
  }
}

// 定义扩展组件样式
@Extend(Button) function globalButtonStyle(color: Color) {
  .height(30)
  .fontSize(14)
  .backgroundColor(color)
}
2、效果
  • 点击新增按钮,可以新增联系人
  • 点击收藏按钮,可以切换是否收藏
    在这里插入图片描述
  • 点击联系人,可以展开当前联系人,查看手机号码
  • 点击上面选择按钮,可以切换选择页面
  • 点击联系人前面复选框,可以选中联系
  • 点击删除按钮,可以删除选中的联系人
    在这里插入图片描述

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

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

相关文章

大模型是如何“炼”成的?揭秘AI背后的训练秘籍!

在当今科技飞速发展的时代,大模型(Large Language Models)已成为人工智能领域的璀璨明星。它们如同经过精心雕琢的艺术品,能够处理各种复杂的任务。然而,这些大模型并非天生如此强大,它们需要经过严格的训练…

VScode | 我的常用插件分享

系列文章目录 本系列文章主要分享作位前端开发的工具之------VScode的使用分享。 文章目录 目录 系列文章目录 文章目录 前言 一、Vetur 三、别名路径跳转 四、Prettier 五、koroFileHeader 六、vue-helper 总结 前言 本文主要分享VScode的好用插件。 一、Vetur Vue的Vetur插…

秒懂C++之vector(上)

目录 一.vector定义 二.vector常用接口 2.1 vector iterator迭代器 2.2 reserve 扩容 2.3 insert 插入 三.对象数组 3.1 例题 3.2 小拓展 一.vector定义 vector本质就是一个顺序表 #include <iostream> #include <vector> using namespace std;void func(ve…

分布式:RocketMQ/Kafka总结(附下载链接)

文章目录 下载链接思维导图 本文总结的是关于消息队列的常见知识总结。消息队列和分布式系统息息相关&#xff0c;因此这里就将消息队列放到分布式中一并进行处理关联 下载链接 链接: https://pan.baidu.com/s/1hRTh7rSesikisgRUO2GBpA?pwdutgp 提取码: utgp 思维导图

大模型微调:参数高效微调(PEFT)方法总结

PEFT (Parameter-Efficient Fine-Tuning) 参数高效微调是一种针对大模型微调的技术&#xff0c;旨在减少微调过程中需要调整的参数量&#xff0c;同时保持或提高模型的性能。 以LORA、Adapter Tuning 和 Prompt Tuning 为主的PEFT方法总结如下 LORA 论文题目&#xff1a;LORA:…

TikTok达人合作:AI与大数据如何提升跨境电商营销效果

在当今数字时代&#xff0c;跨境电商与TikTok达人的合作已成为推动品牌增长和市场拓展的重要力量。随着AI、大数据等先进技术的不断发展和应用&#xff0c;这种合作模式正变得更加高效和精准。本文Nox聚星将和大家探讨在TikTok达人合作中&#xff0c;AI、大数据等技术的具体运用…

PyTorch 的 .pt 文件是什么?以及都能存储什么样的数据格式和复合数据格式?加载 train.pt 文件的一个代码示例

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、PyTorch 的 .pt 文件是什么&#xff1f; .pt 文件的基本概念&#xff1a; .pt 文件是 PyTorch 中特有的一种文件格式&#xff0c;用于保存和加载各类数据。.pt为 PyTorch 的缩写。此文件格式极其灵…

Linux快速安装Jenkins一键部署Maven项目

目录 一、序言二、安装前置准备1、JDK版本要求2、Maven安装3、Git安装 三、Jenkins安装1、Jenkins war包下载2、启动Jenkins3、初始化Jenkins4、Jenkins全局设置 四、Maven项目自动化jar部署项目配置1、创建Maven风格的项目2、丢弃旧的构建3、源码管理配置4、构建配置5、构建后…

华为od 100问 持续分享10-华为OD的面试流程细说

我是一名软件开发培训机构老师&#xff0c;我的学生已经有上百人通过了华为OD机试&#xff0c;学生们每次考完试&#xff0c;会把题目拿出来一起交流分享。 重要&#xff1a;2024年5月份开始&#xff0c;考的都是OD统一考试&#xff08;D卷&#xff09;&#xff0c;题库已经整…

带有扰动观测器的MPC电机控制

模型预测控制(Model Predictive Contro1, MPC)是一种先进的控制策略&#xff0c;虽然具有鲁棒性、建模简单、处理多变量系统、显示约束、预测未来行为和优化性能的能力等优势。它的不足在于预测控制行为的计算需要繁琐的计算量&#xff0c;以及抗干扰能力较弱。这里提出基于扰动…

34 列表常用方法——copy()

列表对象的 copy() 方法返回列表的浅复制。 浅复制&#xff0c;是指生成一个新的列表&#xff0c;并且把原列表中所有元素的引用都都复制到新列表中。 如果原列表中只包含整数、实数、复数等基本类型或元组、字符串这样的不可变类型的数据&#xff0c;一般是没有问题的。但是&a…

黛米·摩尔和她的孙女卢埃塔在这张飘逸的快照很亲密

卢埃塔和她的祖母黛米摩尔显然是最好的朋友&#xff0c;这张飘逸的快照证明了这一点。准备好“哇&#xff01;” 7 月 26 日&#xff0c;摩尔分享了一张非常迷人的照片&#xff0c;照片上有她、她的两个女儿和她的孙女在她昂贵的后院。她在照片中配文说&#xff1a;“夏日&…

SX_初识GitLab_1

1、对GitLab的理解&#xff1a; 目前对GitLab的理解是其本质是一个远程代码托管平台&#xff0c;上面托管多个项目&#xff0c;每个项目都有一个master主分支和若干其他分支&#xff0c;远程代码能下载到本机&#xff0c;本机代码也能上传到远程平台 1.分支的作用&#xff1a…

Home Assistant ESPHome 第一次烧录ESP8266设备记录日志

流程简介 windows PC->usb 数据线->板载usb-ttl->esp8266 connect 编译固件 下载固件 esp web tools 写入固件 编译固件 go esphome add on 1.创建设备 选择ESP8266 2.编写.yaml配置, 3.编译-输出bin 烧录 4.烧录 打开 Web-ESPHome 5.查看日志 查看手机wif…

如何让企业在获客上拥有竞争力?云微客打造流量爆款

做了这么久的短视频&#xff0c;还是没有客户&#xff0c;如果你还在单一账号上死磕&#xff0c;那么就别做爆款的白日梦了&#xff01;因为你的做法是干不过同行的&#xff0c;同行可能早就开通上百个账号在互联网上抢流量了。 想获客只用一个云微客AI矩阵系统&#xff0c;不用…

科普文:深入理解ElasticSearch体系结构

概叙 Elasticsearch是什么&#xff1f; Elasticsearch&#xff08;简称ES&#xff09;是一个分布式、可扩展、实时的搜索与数据分析引擎。ES不仅仅只是全文搜索&#xff0c;还支持结构化搜索、数据分析、复杂的语言处理、地理位置和对象间关联关系等。 官网地址&#xff1a;…

实习日志2之windows上大模型(qwen2-7b)部署

一、模型部署 1、下载ollama(大模型本地部署工具)&#xff0c;并安装 下载网址&#xff1a;https://ollama.com/ ollama是大模型部署方案&#xff0c;对应docker&#xff0c;本质也是基于docker的容器化技术。 2、下载大模型 在命令框&#xff0c;如windows系统在cmd窗口输…

汽车、能源、烟草、电力行业洞见:TDengine 用户大会亮点荟萃

近年来&#xff0c;随着物联网、车联网、工业互联网等前沿技术的迅猛发展&#xff0c;全球数据量呈指数级增长。作为大数据的一个重要组成部分&#xff0c;时序数据因其在实时监控、预测分析和智能决策中的独特优势&#xff0c;正逐步成为数字化转型的关键要素。尤其在 AI 时代…

如何使用Firefox浏览器连接IPXProxy设置海外代理IP教程

​Firefox浏览器是大家上网时经常会使用的一款工具。不过&#xff0c;有时候我们会遇到一些网站无法直接访问的情况。这时候&#xff0c;通过海外代理IP&#xff0c;比如像IPXProxy代理这样的服务&#xff0c;可能就能帮助我们进入那些受限制的网站&#xff0c;获取我们所需的资…

如何通过 CloudCanal 实现从 Kafka 到 AutoMQ 的数据迁移

01 引言 随着大数据技术的飞速发展&#xff0c;Apache Kafka 作为一种高吞吐量、低延迟的分布式消息系统&#xff0c;已经成为企业实时数据处理的核心组件。然而&#xff0c;随着业务的扩展和技术的发展&#xff0c;企业面临着不断增加的存储成本和运维复杂性问题。为了更好地…