ArkTS @Observed、@ObjectLink状态装饰器的使用

 作用

@Observed、@ObjectLink装饰器用于在涉及嵌套对象或者数组元素为对象的场景中进行双向数据同步。

状态的使用

1.嵌套对象

我们将父类设置为@Observed状态,这个时候,子应该设置@ObjectLink才能完成数据的双向绑定,所以我们构建一个组件,让状态变成一个变量来完成属性的状态化。

@Observed
class Person{
  name: string
  age: number
  gf: Person

  constructor(name:string, age: number, gf?: Person) {
    this.name = name
    this.age = age
    this.gf = gf
  }
}

@Entry
@Component
struct Parent {
  @State p: Person = new Person('zhangsan',21,new Person('lisi',18))
  build() {
    Row() {
      Column() {
        Child({p:this.p.gf})
          .onClick(()=>this.p.gf.age++)
      }
      .width('100%')
    }
    .height('100%')
  }
}

@Component
struct Child{
  @ObjectLink p: Person
  build(){
    Column(){
      Text(`${this.p.name} : ${this.p.age}`)
    }
  }
}

2.数组中的对象元素

只要我们的数据 经过了Child的手,也就是使用了@ObjectLink绑定的变量,变量状态的更新都会直接出发视图的更新。

@Observed
class Person{
  name: string
  age: number
  gf: Person

  constructor(name:string, age: number, gf?: Person) {
    this.name = name
    this.age = age
    this.gf = gf
  }
}

@Entry
@Component
struct Parent {
  @State p: Person = new Person('zhangsan',21,new Person('lisi',18))
  @State gfs: Person[] = [
  new Person('wangwu',18),new Person('yangliu',19), ]
  build() {
    Row() {
      Column() {
        Child({p:this.p.gf})
          .onClick(()=>this.p.gf.age++)
        Text('===== 列表 =====')
        ForEach(
          this.gfs,
          p=> {
            Child({p:p}).onClick(()=>p.age++)
          }
        )
      }
      .width('100%')
    }
    .height('100%')
  }
}

@Component
struct Child{
  @ObjectLink p: Person
  build(){
    Column(){
      Text(`${this.p.name} : ${this.p.age}`)
    }
  }
}

 任务统计案例验证

我们在任务统计案例中使用一下这两个状态。

我们现在想要实现一个效果,就是已经完成的任务,让他变成灰色,并且加删除线效果。

// 任务完成样式
@Extend(Text) function finishedTask(){
  .decoration({type:TextDecorationType.LineThrough})
  .fontColor('#b1b2b1')
}
  
Row(){
   if(item.finished){
       Text(item.name)
       .finishedTask()
        }else{
       Text(item.name)
        }
      Checkbox()
      .select(item.finished)
      .onChange(val=>{
     item.finished = val
    // 通过过滤方法 更新已完成的任务数量
      this.handleTaskChange()
    })
}

我们通过if判断每个任务的状态来决定使用哪种效果,发现不能实现我们的效果。因为foreach遍历数组,等同于给数组元素的属性来改变,正巧我们要修改的属性是一个对象,所以我们的修改是不会触发视图的更新的,所以我们应该使用@Observed、@ObjectLink状态来完成这个案例。 

所以我们来给需要实现的嵌套数组的对象加上状态。

我们给最原始的类Task加上@Observed状态,封装循环产生的Row给item加上@ObjectLink状态,由于我们的组件中,没有状态改变的函数,我们先去掉,先完成样式的修改。



@Observed
class Task{
  static id: number = 1
  // 任务名称
  name: string = `任务${Task.id++}`
  // 任务状态: 是否完成
  finished: boolean = false
}

// 统计的卡片样式
@Styles function card(){
  .width('95%')
  .padding(20)
  .backgroundColor(Color.White)
  .borderRadius(15)
  .shadow({radius: 6,color: '#1f0000',offsetX:2,offsetY:4})
}

// 任务完成样式
@Extend(Text) function finishedTask(){
  .decoration({type:TextDecorationType.LineThrough})
  .fontColor('#b1b2b1')
}


// 任务统计信息
class StaticInfo{
  totalTask: number = 0
  finishTask: number = 0
}

@Entry
@Component
struct PropPage {
  // 统计信息
  @Provide stat: StaticInfo = new StaticInfo()

  build() {
      Column({space:10}) {
        // 1.任务进度卡片
        TaskStatistics()
        // 2.任务列表
        TaskList();
      }
      .width('100%')
      .height('100%')
      .backgroundColor('#f1f2f3')
  }

}


@Component
struct TaskStatistics {

  @Consume stat: StaticInfo

  build(){
    Row(){
      Text("任务进度")
        .fontSize(30)
        .fontWeight(FontWeight.Bold)
      Stack(){
        Progress({
          value:this.stat.finishTask,
          total:this.stat.totalTask,
          type:ProgressType.Ring
        })
          .width(100)
        Row(){
          Text(this.stat.finishTask.toString())
            .fontSize(24)
            .fontColor('#36d')
          Text(' / ' +this.stat.totalTask.toString())
            .fontSize(24)
        }
      }
    }
    .card()
    .margin({top:20,bottom:10})
    .justifyContent(FlexAlign.SpaceEvenly)
  }
}

@Component
struct TaskList {
  // 任务数量
  @State tasks: Task[] = []
  @Consume stat: StaticInfo
  // 通过过滤方法 更新已完成的任务数量
  handleTaskChange(){
    // 更新任务总数量
    this.stat.totalTask = this.tasks.length
    // 已经完成的任务数量
    this.stat.finishTask = this.tasks.filter(item => item.finished).length
  }
  build(){
      Column(){
        // 2.新增任务按钮
        Button('新增任务')
          .width(200)
          .onClick(()=>{
            // 1.新增任务
            this.tasks.push(new Task())
            // 2.更新任务数组
            this.stat.totalTask = this.tasks.length
          })
        // 3.卡片列表
        List({space:10}){
          ForEach(
            this.tasks,
            (item: Task,index)=>{
              ListItem(){
                TaskItem({item:item})
              }
              .swipeAction({end:this.DeleteButton(index)})
            }
          )
        }
        .width('100%')
        .layoutWeight(1)
        .alignListItem(ListItemAlign.Center)
      }
  }
  @Builder DeleteButton(index: number){
    Button("删除")
      .onClick(()=>{
        this.tasks.splice(index,1)
        this.handleTaskChange()
      })
  }
  }

@Component
struct TaskItem {

  @ObjectLink item: Task
  build(){
    Row(){
      if(this.item.finished){
        Text(this.item.name)
          .finishedTask()
      }else{
        Text(this.item.name)
      }
      Checkbox()
        .select(this.item.finished)
        .onChange(val=>{
          this.item.finished = val
          // 通过过滤方法 更新已完成的任务数量
          // this.handleTaskChange()
        })
    }
    .card()
    .justifyContent(FlexAlign.SpaceBetween)
  }
}

我们会发现 点击我们的完成勾选,我们的颜色还有删除线的状态是成功的体现出来的,所以我们的嵌套数组双向绑定是成功的。

现在我们来补全功能,更新我们的完成状态。

方法传递

我们可以通过方法传递来实现方法的公用。

 

@Component
struct TaskItem {
  @ObjectLink item: Task
  onTaskChange: () => void
  build(){
    Row(){
      if(this.item.finished){
        Text(this.item.name)
          .finishedTask()
      }else{
        Text(this.item.name)
      }
      Checkbox()
        .select(this.item.finished)
        .onChange(val=>{
          this.item.finished = val
          // 通过过滤方法 更新已完成的任务数量
          this.onTaskChange();
        })
    }
    .card()
    .justifyContent(FlexAlign.SpaceBetween)
  }
}

我们在taskItem方法中写入一个函数,在调用的时候将函数传入。 这样就相当于我们在taskItem中调用了这个方法。 

然后我们会发现仍然没有实现。因为在子组件中this的指向不正确。

当方法传递的时候,this的指向要确认,因为调方法的人改变了。

所以我们要确保传递方法的时候,this的指向不能改变。这时候我们需要使用到一个api

bind(this)

这时候我们就可以完全实现效果了。 

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

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

相关文章

控制理论simulink+matlab

这里写目录标题 根轨迹二级目录三级目录 根轨迹 z [-1]; %开环传递函数的零点 p [0 -2 -3 -4]; %开环传递函数的系统极点 k 1; %开环传递函数的系数,反映在比例上 g zpk(z,p,k); %生成开环传递函数%生成的传递函数如下 % (s1) % -------------…

Vue3-23-组件-依赖注入的使用详解

什么是依赖注入 个人的理解 : 依赖注入,是在 一颗 组件树中,由 【前代组件】 给 【后代组件】 提供 属性值的 一种方式 ;这种方式 突破了 【父子组件】之间通过 props 的方式传值的限制,只要是 【前代组件】提供的 依…

「Qt Widget中文示例指南」如何创建一个计算器?(三)

Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写,所有平台无差别运行,更提供了几乎所有开发过程中需要用到的工具。如今,Qt已被运用于超过70个行业、数千家企业,支持数百万设备及应用。 本文将展示如何使用…

【开源GIS】如何高效地学习GIS开源项目?一上来就读源码你就输了!

目录 🔥前言Step 1: 熟悉项目Step 2: Hello worldStep 3: 深入了解和使用Step 4: 可以看源码了!Step 5: API 二次封装Step 6: 持续关注和学习 🔥前言 都知开源好,只看源码看不懂,是俺太菜了?no no no&#…

kubeadm方式重置k8s集群

以kubeadm方式部署的k8s,当出现问题,排查解决的难度会非常大,如果是实验环境,直接进行集群重置即可,如果是生产环境,如果集群已经崩掉了,而且短时间时间内无法定位原因的情况的下,建…

Ansible(一)

Ansible: 远程操作主机功能: 自动化运维(playbook剧本YAML) 是基于Python开发的配置管理应用部署攻具,在自动化运维当中,现在是异军突起 Ansible能批量配置,部署,管理上千台主机&#xff0c…

基于vite 初始化vue3项目并引入Vue Router和Ant Design Vue

基于vite 初始化vue3项目并引入常用的功能、组件。 Vue RouterAnt Design Vue 系列文章指路👉 系列文章-基于Vue3创建前端项目并引入、配置常用的库和工具类 文章目录 创建ViteVue项目创建并运行WebStorm无法识别,需要在vite.config.js中定义alias 引入…

GNSS模块在野外探险中的应用

野外探险是一项令人兴奋的活动,而GNSS(全球导航卫星系统)模块的广泛应用为探险者提供了精准的导航、位置跟踪和安全保障。本文将深入探讨GNSS模块在野外探险中的应用,以及它如何改变和增强探险体验。 精准导航与路径规划&#xf…

基于SpringBoot的大病保险管理系统 JAVA简易版

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统配置维护2.2 系统参保管理2.3 大病保险管理2.4 大病登记管理2.5 保险审核管理 三、系统详细设计3.1 系统整体配置功能设计3.2 大病人员模块设计3.3 大病保险模块设计3.4 大病登记模块设计3.5 保险审核模块设计 四、…

VS Code配置Go语言开发环境

提示:首先这是一个新型语言,最好把vscode更新到最新版。 1:去官网下载Go语言编译器,之后配置到系统环境中,能看到版本就行。 2:创建一个文件夹,存放go的工具文件,我的在D:\GoFile\G…

职场如何与不同级别的领导打交道?学会3个小妙招吃遍天下

职场如何与不同级别的领导打交道?学会3个小妙招吃遍天下 简介 刚步入职场的时候,很多新人小白会患上权威恐惧症,简单来说就是害怕与领导打交道,职位越大的领导越害怕。有领导在的地方有多远就躲多远,更别说主动去找领…

嵌入式串口输入详细实例

学习目标 掌握串口初始化流程掌握串口输出单个字符掌握串口输出字符串掌握通过串口printf熟练掌握串口开发流程学习内容 需求 串口循环输出内容到PC机。 串口数据发送 添加Usart功能。 首先,选中Firmware,鼠标右键,点击Manage Project Items 接着,将gd32f4xx_usart.c添…

[PyTorch][chapter 8][李宏毅深度学习][Back propagation]

前言: 反向传播算法(英:Backpropagation algorithm,简称:BP算法)是一种监督学习算法,常被用来训练多层感知机。 它用于计算梯度计算中,降低误差。 目录: 链式法则 模型简介(Model) 损失函…

【YOLOv8量化】普通CPU上加速推理可达100+FPS

NNCF介绍 OpenVINO2023版本衍生出了一个新支持工具包NNCF(Neural Network Compression Framework – 神经网络压缩框架),通过对OpenVINO IR格式模型的压缩与量化更好的提升模型在OpenVINO框架上部署的推理性能,github。 https://github.com/openvinoto…

银河麒麟v10 安装mysql 8.35

银河麒麟v10 安装mysql 8.35 1、下载Mysql安装包2、安装Mysql 8.352.1、安装依赖包2.2、安装Mysql2.3、安装后配置 1、下载Mysql安装包 访问官网下载链接 链接: https://dev.mysql.com/downloads/mysql/ 选择如下 点击下载按钮 下载安装包 2、安装Mysql 8.35 官方安装文档…

AWS Linux安装桌面并远程访问

文章目录 小结问题及解决参考 小结 在AWS Linux安装了桌面并进行远程访问。 问题及解决 需要使用过程桌面访问AWS Linux,这里在AWS服务器安装并使用Amazon Linux 2 MATE desktop。 检查OS版本: [ec2-userip-10-0-3-241 ~]$ grep PRETTY_NAME /etc/o…

算法设计与分析2023秋-头歌实验-实验七 动态规划

文章目录 第1关:数塔问题任务描述相关知识编程要求解题思路测试说明参考答案 第2关:最长公共子序列任务描述相关知识编程要求解题思路:测试说明参考答案 第3关:求序列-2 11 -4 13 -5 -2的最大子段和任务描述相关知识编程要求解题思…

可实现RSSD云硬盘120万IOPS的SPDK IO路径优化

一. 简介 用户对超高并发、超大规模计算等需求推动了存储硬件技术的不断发展,存储集群的性能越来越好,延时也越来越低,对整体IO路径的性能要求也越来越高。在云硬盘场景中,IO请求从生成到后端的存储集群再到返回之间的IO路径比较…

less基础介绍

什么是less? Less是一个C5S预处理器,Less文件后缀是,less。扩充了 CSS 语言,使CSS 具备一定的逻辑性、计算能力 注意事项: 浏览器不识别 Less 代码,目前阶段,网页要引入对应的 CSS 文件 VS Code 插件: Easy LESS,保存 …

JVM快速入门

JVM 字节码 字节码文件的组成 字节码由五个部分组成:基础信息 常量池 字段 方法 属性 基础信息: 魔数、字节码文件对应的版本号、访问标识(public final)、该类的父类索引、该类实现哪些接口的索引 魔数:文件无法…
最新文章