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 }) } } }