第七讲_ArkTS装饰器(四)

发布时间:2024年01月20日

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

上一篇博文ArkTS装饰器(三)中,介绍的@Prop装饰器和@Link装饰器都是父子间的同步。@Provide装饰器和@Consume装饰器,应用于与后代组件的双向数据同步,应用于状态数据在多个层级之间传递的场景。

1.1 @Provide装饰器和@Consume装饰器特点

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

1.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++
        })
    }
  }
}

在这里插入图片描述

1.3 @Provide变量的传递规则

父组件中哪些变量可以用来初始化子组件中的@Provide变量?
@Provide变量可以用来初始化子组件中的哪些变量?
在这里插入图片描述

1.4 @Consume变量的传递规则

@Consume变量禁止被父组件初始化。
@Consume变量可以用来初始化子组件中的哪些变量?
在这里插入图片描述

2. @Observed装饰器和@ObjectLink装饰器

上一篇博文ArkTS装饰器(三)和上文所述的装饰器仅能观察到第一层的变化,对于多层嵌套的情况,比如二维数组、数组项class、class的属性是class,它们的第二层的属性变化是无法观察到的。这个时候就需要用到@Observed/@ObjectLink装饰器。

2.1 @Observed装饰器和@ObjectLink装饰器特点

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

2.2 @Observed装饰器和@ObjectLink装饰器使用示例

示例中,this.classA.classB.namethis.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
        })
    }
  }
}

在这里插入图片描述

2.3 @ObjectLink变量的传递规则

父组件中哪些变量可以用来初始化子组件中的@ObjectLink变量?
@ObjectLink变量可以用来初始化子组件中的哪些变量?
在这里插入图片描述

文章来源:https://blog.csdn.net/wenqi1992/article/details/135710738
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。