@ObjectLink装饰器

1)概念

在鸿蒙开发中会使用@State来装饰我们的变量,一旦变量发生变化,页面更新

遇到了复杂的数据结构,数据更新会有差别

比如嵌套对象,或者数组对象。

嵌套对象:如果修改的内层对象的属性,默认页面无法检测更新。

数组对象:修改数组页面都能检测变化,修改数组里面的对象属性,页面无法检测更新

(2)嵌套对象

代码演示效果

​
class Pat {
  id:string = ''
  name:string = ''
  type:string = ''
​
  constructor(id:string,name:string,type:string) {
    this.id = id
    this.name = name
    this.type = type
  }
}
​
class Student {
  id:string = ''
  name:string = ''
  pat:Pat
​
  constructor(id:string,name:string,pat:Pat) {
    this.id = id
    this.name = name
    this.pat = pat
  }
}
​
@Entry
@Component
struct ObjectLinkPage {
  @State message: string = 'Hello World';
​
  //使用State修饰
  @State stu1:Student = new Student('1','迪丽热巴',new Pat('1','大黄','金毛'))
​
  build() {
    Column() {
      Text(`${JSON.stringify(this.stu1)}`)
        .onClick(() =>{
          // this.stu1.name = '小谷' //修改第一层数据,可以修改
          // this.stu1.pat.name = '小黑' //修改stu1里的对象属性,发现没有反应无法修改
          const pat1 = new Pat('2','小黑','拉布拉多')
          this.stu1.pat = pat1 //以这种方式整体修改,等于修改的第一层,可以修改
        })
    }
    .height('100%')
    .width('100%')
  }
}

点击修改学生按钮:页面可以立即更新,修改学生信息可以在页面检测到

点击修改宠物按钮:页面不会更新,因为只能检测学生属性变化,无法深度监听内部对象变化

ArkTs为什么要这么做呢?

优势:如果做成这样,可以直接操作的话,性能消耗比较大

(3)对象数组

对象数组进行循环遍历的时候,如果直接操作数组中的元素,数组的变化能引起页面的更新,如果操作数组里面的对象属性,页面无法检测更新

@State school:Array<Student> = [
  new Student('1','迪丽热巴',new Pat('1','大黄','金毛')),
  new Student('2','古力娜扎',new Pat('2','花花','泰迪'))
]
ForEach(this.school,(item:Student,index:number) => {
  Text(`${JSON.stringify(item)}`)
    .fontSize(25)
    .fontColor(Color.Red)
  Button('点击修改学生名字')
    .onClick(() => {
      item.name = '默认名字'//发现点击之后没有效果,页面无法检测更新
    })
}, (item:Student) => item.id)
Button('数组里添加一个数据').onClick((event: ClickEvent) => {
//页面可以检测更新
  this.school.push(new Student('3','丫丫',new Pat('3','嘿嘿','二哈')))
})

(4)嵌套装饰器的使用

@ObjectLink和@Observed装饰器一般要一起使用,才能实现对象监听

@Observed放在类上面(model数据约束上面)

@ObjectLink放在组件中定义数据,无法在entry中使用

  • 对数组的深度更新的解决方案

在Student.ets中

export class Pat {
  id:string = ''
  name:string = ''
  type:string = ''
​
  constructor(id:string,name:string,type:string) {
    this.id = id
    this.name = name
    this.type = type
  }
}
​
@Observed
export class Student {
  id:string = ''
  name:string = ''
  pat:Pat
​
  constructor(id:string,name:string,pat:Pat) {
    this.id = id
    this.name = name
    this.pat = pat
  }
}

在父组件中

@State school:Array<Student> = [
  new Student('1','迪丽热巴',new Pat('1','大黄','金毛')),
  new Student('2','古力娜扎',new Pat('2','花花','泰迪'))
]
ForEach(this.school,(item:Student,index:number) => {
  ObjectLinkList({item:item})
}, (item:Student) => item.id)

在子组件中

@Component
export struct ObjectLinkList {
  @ObjectLink item:Student
  build() {
    Column() {
      Text(`${JSON.stringify(this.item)}`)
        .fontSize(25)
        .fontColor(Color.Red)
      Button('点击修改学生名字')
        .onClick(() => {
          this.item.name = '默认名字'//发现点击之后修改了
        })
    }
    .width('100%')
    .height('120')
​
  }
}

子组件接收的数据就是你要监听的对象

@ObjectLink配合@Observed使用就能实现对指定的对象进行深度监听

  • 对嵌套对象深度检测的解决方法
    @State stu1:Student = new Student('1','迪丽热巴',new Pat('1','大黄','金毛'))
    ObjectLinkList2({pat:this.stu1.pat})
    @ObjectLink pat:Pat
      // pat:Student = new Student('1','迪丽热巴',new Pat('1','大黄','金毛'))
      build() {
        Column(){
          Text(`${JSON.stringify(this.pat)}`)
            .onClick(() =>{
              this.pat.name = '小谷' //修改第一层数据,可以修改
            })
          Text(`${JSON.stringify(this.pat)}`)
            .onClick(() => {
              this.pat.name = '哈哈哈'
            })
        }
      }

    总结:如果页面上只是渲染嵌套对象,那我们无需进行干预,直接渲染出来就可以了但是如果要针对嵌套对象进行修改,一定要创建一个子组件,将这个对象传递给子组件专门进行页面渲染以及修改。也需要给model数据约束增加@Observed以及@ObjectLink来接收修改对象

(5)属性装饰器@ObservedV2装饰器和@Trace装饰器

为了解决@ObjectLink配合@Observed装饰器在使用时繁琐的步骤,推出了@ObservedV2装饰器和@Trace,可以对对象进行深度检测,

代码实例:

​
@ObservedV2
export class Pat2 {
  id:string = ''
  @Trace name:string = ''
  type:string = ''
​
  constructor(id:string,name:string,type:string) {
    this.id = id
    this.name = name
    this.type = type
  }
}
​
@ObservedV2
export class Student2 {
  id:string = ''
  @Trace name:string = ''
  pat:Pat2
​
  constructor(id:string,name:string,pat:Pat2) {
    this.id = id
    this.name = name
    this.pat = pat
  }
}

在类中使用@ObservedV2说明要监测的对象,@Trace说明要监测的属性,未被@Trace装饰的属性不会被监测到

stu1:Student2 = new Student2('1','迪丽热巴',new Pat2('1','大黄','金毛'))
​
  build() {
    Column() {
      Text(`${this.stu1.name}`)
        .onClick(()=>{
          this.stu1.name = '古镇'
          console.log('点击了第一个')
        })
      Text(`${this.stu1.pat.name}`)
        .onClick(()=>{
          this.stu1.pat.name = '啦啦啦啦'
          console.log('点击了第二个')
        })
​
    }

在使用时就可以对嵌套对象的属性进行检测

@ObservedV2装饰器和@Trace装饰器无法与@status混合使用

@ObservedV2仅能装饰class,无法装饰自定义组件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值