ArkTS装饰器(四)
1. @Provide装饰器和@Consume装饰器
上一篇博文ArkTS装饰器(三)中,介绍的@Prop
装饰器和@Link
装饰器都是父子间的同步。@Provide
装饰器和@Consume
装饰器,应用于与后代组件的双向数据同步,应用于状态数据在多个层级之间传递的场景。
1.1 @Provide装饰器和@Consume装饰器特点
@Provide
装饰的状态变量自动对其所有后代组件可用。- 后代通过使用
@Consume
去获取@Provide
提供的变量。 @Provide
和@Consume
之间是双向数据同步。@Provide
变量在声明时必须指定类型和本地初始化。@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.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
})
}
}
}
2.3 @ObjectLink变量的传递规则
父组件中哪些变量可以用来初始化子组件中的@ObjectLink变量?
@ObjectLink变量可以用来初始化子组件中的哪些变量?