ArkTS @Observed和@ObjectLink装饰器的用法(附带实例)
在开发过程中,不仅会用到简单的数据类型,一些复杂的数据类型也是经常需要处理的。对于复杂数据类型,比如二维数组或者数组项是 class,或者 class 的属性是 class 等这类数据,它们的第二层属性的变化是无法动态渲染的。
基于此,HarmonyOS 提供了两个装饰器 @Observed 和 @ObjectLink,用来操作此类数据。
@Observed 装饰器用于监听对象属性的变化,而 @ObjectLink 则用于链接两个对象,确保它们的状态同步。
@Observed 类装饰器用于装饰 class,不需要参数,用于观察属性变化,配合 @ObjectLink 使用。@ObjectLink 变量装饰器用于指定必须为 @Observed 装饰的 class 实例的变量,支持复杂类型,如 Date、Array、Map、Set 以及它们的联合类型。@ObjectLink 装饰的变量是只读的,不能改变分配的值。
@Observed 和 @ObjectLink 装饰器用于在涉及嵌套对象或数组元素为对象的场景中进行双向数据同步。
接下来从 @Observed 和 @ObjectLink 的使用场景开始,详细介绍两个装饰器的使用。
观察如下图所示的基本案例:

图 1 基本案例
在这个案例中可以发现以下几种现象:
子组件的单击事件可以改成如下方法,效果一致:
完整代码如下:
基于此,HarmonyOS 提供了两个装饰器 @Observed 和 @ObjectLink,用来操作此类数据。
@Observed 装饰器用于监听对象属性的变化,而 @ObjectLink 则用于链接两个对象,确保它们的状态同步。
@Observed 类装饰器用于装饰 class,不需要参数,用于观察属性变化,配合 @ObjectLink 使用。@ObjectLink 变量装饰器用于指定必须为 @Observed 装饰的 class 实例的变量,支持复杂类型,如 Date、Array、Map、Set 以及它们的联合类型。@ObjectLink 装饰的变量是只读的,不能改变分配的值。
@Observed 和 @ObjectLink 装饰器用于在涉及嵌套对象或数组元素为对象的场景中进行双向数据同步。
接下来从 @Observed 和 @ObjectLink 的使用场景开始,详细介绍两个装饰器的使用。
观察如下图所示的基本案例:

图 1 基本案例
在这个案例中可以发现以下几种现象:
- 单击子组件的元素时,对应的数据会同步更新;
- 单击父组件元素时,对应的数据不会同步更新,相反子组件的数据会进行更新。
子组件的单击事件可以改成如下方法,效果一致:
Child({ p: item }).onClick(() => { item.age++ })
完整代码如下:
// 被观察的嵌套数据模型 @Observed class Person { name: string age: number girlfriend?: Person | undefined // 可选的嵌套对象 constructor(name: string, age: number, girlfriend?: Person) { this.name = name this.age = age this.girlfriend = girlfriend } } // 父组件 @Entry @Component struct Demo { @State p: Person = new Person('小明', 20, new Person('李华', 19)) @State gfs: Person[] = [ new Person('韩梅梅', 20), new Person('刘夏', 21), ] build() { Column() { // 传值:把当前对象的 girlfriend 传给子组件 Child({ p: this.p.girlfriend! }) Text('女友的列表') // 列表子组件:点击每项让对应对象的 age++ ForEach(this.gfs, (item: Person) => { Child({ p: item }) .onClick(() => { item.age++ }) }) Text('父组件中嵌套数据的变化') // 直接在父组件展示并操作数据 ForEach(this.gfs, (item: Person) => { Text(`姓名:${item.name},年龄 ${item.age}`) .onClick(() => { item.age++ }) }) } .width('100%') .height('100%') } } // 子组件:通过 @ObjectLink 接收 Person 对象 @Component struct Child { @ObjectLink p: Person build() { Column() { Text(`姓名:${this.p.name}, 年龄 ${this.p.age}`) } } }