ArkTs学习之ArkTS装饰器@Provide装饰器和@Consume装饰器 与 @Observed装饰器和@ObjectLink装饰器(五)

一、@Provide装饰器和@Consume装饰器

@Prop装饰器和@Link装饰器都是父子间的同步。@Provide装饰器和@Consume装饰器,应用于与后代组件的双向数据同步,应用于状态数据在多个层级之间传递的场景。

@Provide作为数据的提供方,可以更新其子孙节点的数据,并触发页面渲染。@Consume在感知到@Provide数据的更新后,会触发当前自定义组件的重新渲染。

使用方法:

1 父类中用@Provide(“变量别称”)变量名 : 类型 = 初始化

@Provide(“orderId”) orderId: number = 0;

2 孙子类中用@Consume(“变量别称”)变量名 : 类型

@Consume(“orderId”) orderId: number

3 在父类中调用 改变值,后代组件就知道(后代组件,都不需要传递参数,就知道父组件的变量变化)

1. @Provide装饰器和@Consume装饰器特点

@Provide装饰的状态变量自动对其所有后代组件可用。
后代通过使用@Consume去获取@Provide提供的变量。
@Provide和@Consume之间是双向数据同步。
@Provide变量在声明时必须指定类型和本地初始化。
@Consume变量在声明时必须指定类型,可以不本地初始化,但禁止父组件初始化。

2. @Provide装饰器和@Consume装饰器使用示例

组件Parent中引入了Child组件,Child组件中引入了Grandson组件,三层关系之间通过@Provide和@Consume来实现跨层的数据双向同步。

@Entry
@Component
struct Parent {
  // 定义一个状态变量
  @Provide count: number = 0;

  build() {
    Column() {
      // 使用自定义Child组件
      Child()
      Text(`Parent组件中count=${this.count}`)
      // Button是系统组件,添加一个点击事件,点击一次就给count + 1
      Button("Parent组件中的点击+1")
        .onClick(() => {
          this.count++
        })
    }
  }
}

@Component
struct Child {
  // 定义一个@Consume变量
  // 获取祖先组件中@Provide提供的变量
  @Consume count: number;

  build() {
    Column() {
      // 使用自定义Grandson组件
      Grandson()
      Text(`Child组件中count=${this.count}`)
      Button("Child组件中的点击+1")
        .onClick(() => {
          this.count++
        })
    }
  }
}

@Component
struct Grandson {
  // 获取祖先组件中@Provide提供的变量
  @Consume count: number;

  build() {
    Column() {
      Text(`Grandson组件中count=${this.count}`)
      Button("Grandson组件中的点击+1")
        .onClick(() => {
          this.count++
        })
    }
  }
}

3. @Provide变量的传递规则

4. @Consume变量的传递规则

二、 @Observed装饰器和@ObjectLink装饰器

对于多层嵌套的情况,比如二维数组、数组项class、class的属性是class,它们的第二层的属性变化是无法观察到的。这个时候就需要用到@Observed/@ObjectLink装饰器。

1. @Observed装饰器和@ObjectLink装饰器特点

@Observed用于修饰类,被@Observed装饰的类,可以观察到嵌套的变化;
@ObjectLink用在子组件中,@ObjectLink装饰的状态变量用于接收@Observed装饰的类的实例,和父组件中对应的状态变量建立双向数据绑定。
@ObjectLink装饰器不能在@Entry装饰的自定义组件中使用。
@Observed除了搭配@ObjectLink使用,还可以搭配@Prop使用。

2. @Observed装饰器和@ObjectLink装饰器使用示例

示例中,this.classA.classB.name和this.classA.classB.age属于第二层变化,@State无法观察到第二层的变化,因此Parent组件中的Text不会变化。@ObjectLink可以观察到,所以Child组件中的Text会变化。

@Observed
class ClassA {
  classB: ClassB;

  constructor(classB: ClassB) {
    this.classB = classB;
  }
}

@Observed
class ClassB {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

@Entry
@Component
struct Parent {
  // 定义一个状态变量
  @State classA: ClassA = new ClassA(new ClassB("张三", 18));

  build() {
    Column() {
      // 使用自定义Child组件,父组件传参初始化子组件
      Child({classB:this.classA.classB})
      // this.classA.classB.name和this.classA.classB.age属于第二层变化,@State无法观察到第二层的变化
      Text(`Parent组件中name=${this.classA.classB.name},age=${this.classA.classB.age}`)
      // Button是系统组件,添加一个点击事件
      Button("Parent组件中的点击age+1")
        .onClick(() => {
          this.classA.classB.age += 1
        })
    }
  }
}

@Component
struct Child {
  // 定义一个@ObjectLink变量,@ObjectLink变量的类型所属类必须被@Observed修饰
  // 不可以本地初始化
  @ObjectLink classB: ClassB;

  build() {
    Column() {
      Text(`Child组件中name=${this.classB.name},age=${this.classB.age}`)
      Button("Child组件中的点击age+1")
        .onClick(() => {
          this.classB.age += 1
        })
    }
  }
}

3. @ObjectLink变量的传递规则

posted on 2024-04-01 23:43  梁飞宇  阅读(735)  评论(0)    收藏  举报