HarmonyOS next之深度监听对象数组变化

前言:

在实际的应用开发过程中,我们会发现之前提到的装饰器存在一定的局限性。它仅仅能够观察到第一层的变化,而在开发中,应用常常会依据自身需求封装数据模型。当遇到多层嵌套的情况时,就会出现问题。例如二维数组,或者数组项是 class,又或者 class 的属性是 class,这种情况下,它们第二层的属性变化是无法被观察到的。这一不足严重影响了对复杂数据结构变化的监测。不过,有解决办法,那就是 @Observed/@ObjectLink 装饰器,它们的出现为解决多层嵌套数据结构属性变化观察问题提供了可能,能够更好地满足开发中对复杂数据变化监测的要求,保障应用开发中数据处理的准确性和有效性。

@ObjectLink和@Observed类装饰器用于在涉及嵌套对象或数组的场景中进行双向数据同步

这里对官网文档进行一个解释说明

官网文档地址:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides...

let NextID: number = 1;

// 使用装饰器监听数组对象
@Observed
class Info {
  public id: number;
  public info: number;

  constructor(info: number) {
    this.id = NextID++;
    this.info = info;
  }
}
// ObjectLink一定要放在子组件里面
@Component
struct Child {
  // 子组件Child的@ObjectLink的类型是Info
  @ObjectLink info: Info;
  label: string = 'ViewChild';

  build() {
    Row() {
      Button(`ViewChild [${this.label}] this.info.info = ${this.info ? this.info.info : "undefined"}`)
        .width(320)
        .margin(10)
        .onClick(() => {
          this.info.info += 1;
        })
    }
  }
}

@Entry
@Component
struct Parent {
  // 即使是在函数之中请求的数据,赋值时也要使用 new ,否则监听不到函数变化
  // Parent中有@State装饰的Info[]
  @State arrA: Info[] = [new Info(0), new Info(0)];

  build() {
    Column() {
      ForEach(this.arrA,
        (item: Info) => {
          Child({ label: `#${item.id}`, info: item })
        },
        (item: Info): string => item.id.toString()
      )
      // 使用@State装饰的数组的数组项初始化@ObjectLink,其中数组项是被@Observed装饰的Info的实例
      Child({ label: `ViewChild this.arrA[first]`, info: this.arrA[0] })
      Child({ label: `ViewChild this.arrA[last]`, info: this.arrA[this.arrA.length-1] })

      Button(`ViewParent: reset array`)
        .width(320)
        .margin(10)
        .onClick(() => {
          this.arrA = [new Info(0), new Info(0)];
        })
      Button(`ViewParent: push`)
        .width(320)
        .margin(10)
        .onClick(() => {
          this.arrA.push(new Info(0))
        })
      Button(`ViewParent: shift`)
        .width(320)
        .margin(10)
        .onClick(() => {
          if (this.arrA.length > 0) {
            this.arrA.shift()
          } else {
            console.log("length <= 0")
          }
        })
      Button(`ViewParent: item property in middle`)
        .width(320)
        .margin(10)
        .onClick(() => {
          this.arrA[Math.floor(this.arrA.length / 2)].info = 10;
        })
      Button(`ViewParent: item property in middle`)
        .width(320)
        .margin(10)
        .onClick(() => {
          this.arrA[Math.floor(this.arrA.length / 2)] = new Info(11);
        })
    }
  }
}

以上就是我们对数组对象的比较完美的更新方式


flfljh
1 声望1 粉丝