HarmonyOS—ArkTS中@Observed和@ObjectLink装饰器的嵌套类对象属性变化【鸿蒙应用开发】
@[toc]
ARKTS中@Observed和@ObjectLink装饰器的嵌套类对象属性变化
在ARKTS的开发中,为了更好地支持嵌套类对象的属性变化,引入了@Observed
和@ObjectLink
两个装饰器。这两个装饰器允许在涉及嵌套对象或数组的情境中进行双向数据同步,特别是在二维数组、数组项class、或者class的属性是class等多层嵌套的情况下。
@Observed 类装饰器
说明
@Observed
类装饰器用于标记一个类,使其属性的变化能够被观察到。
装饰器参数
无
类装饰器的使用
装饰class,需要放在class的定义前,使用new
创建类对象。
@Observed
class ExampleClass {
public prop1: number;
constructor(prop1: number) {
this.prop1 = prop1;
}
}
注意: 使用@Observed
装饰class会改变class原始的原型链,因此需要谨慎使用,特别是当@Observed
和其他类装饰器装饰同一个class时可能会引发问题。
@ObjectLink 变量装饰器
说明
@ObjectLink
变量装饰器用于在子组件中与父组件中的状态变量建立双向数据绑定,接收@Observed
装饰的类的实例。
装饰器参数
无
同步类型
不与父组件中的任何类型同步变量。
允许装饰的变量类型
必须为被@Observed
装饰的class实例,同时需要指定类型。
不支持简单类型,可以使用@Prop
。
被装饰变量的初始值
不允许。
举例
@ObjectLink
public objLink: ExampleClass;
注意: 被@ObjectLink
装饰的变量不能被直接赋值,如果需要赋值操作,请使用@Prop
。
装饰器的限制条件
-
使用
@Observed
装饰class会改变class原始的原型链,因此需要注意@Observed
和其他类装饰器装饰同一个class可能会带来问题。 -
@ObjectLink
装饰器不能在被@Entry
装饰的自定义组件中使用。
观察变化和行为表现
观察的变化
-
对于
@Observed
装饰的类,如果其属性为非简单类型(如class、Object或者数组),这些属性也需要被@Observed
装饰,否则将观察不到其属性的变化。@Observed class ClassA { public c: number; constructor(c: number) { this.c = c; } } @Observed class ClassB { public a: ClassA; public b: number; constructor(a: ClassA, b: number) { this.a = a; this.b = b; } }
-
@ObjectLink
只能接收被@Observed
装饰的class的实例,可以观察到其属性的数值变化,包括数组项的替换和class属性的变化。
框架行为
-
初始渲染:
@Observed
装饰的class实例会被不透明的代理对象包装,代理了class上的属性的setter和getter方法。- 子组件中
@ObjectLink
装饰的从父组件初始化,接收被@Observed
装饰的class的实例,@ObjectLink
的包装类会将自己注册给@Observed
class。
-
属性更新: 当
@Observed
装饰的class属性改变时,会走到代理的setter和getter,然后遍历依赖它的@ObjectLink
包装类,通知数据更新。
使用场景
1. 嵌套对象
以下是嵌套类对象的数据结构的示例:
@Observed
class ClassA {
public id: number;
public c: number;
constructor(c: number) {
this.id = NextID++;
this.c = c;
}
}
@Observed
class ClassB {
public a: ClassA;
constructor(a: ClassA) {
this.a = a;
}
}
这个例子中,ClassB
被@Observed
装饰,其成员变量的赋值的变化是可以被观察到的。对于ClassA
,没有被@Observed
装饰,其属性的修改不能被观察到。
2. 对象数组
对象数组是一种常用的数据结构。以下示例展示了数组对象的用法:
@Component
struct ViewA {
// 子组件ViewA的@ObjectLink的类型是ClassA
@ObjectLink a: ClassA;
label: string = 'ViewA1';
build() {
Row() {
Button(`ViewA [${this.label}] this.a.c = ${this.a.c} +1`)
.onClick(() => {
this.a.c += 1;
})
}
}
}
@Entry
@Component
struct ViewB {
// ViewB中有@State装饰的ClassA[]
@State arrA: ClassA[] = [new ClassA(0), new ClassA(0)];
build() {
Column() {
ForEach(this.arrA,
(item) => {
ViewA({
label: `#${item.id}`, a: item })
},
(item) => item.id.toString()
)
// 使用@State装饰的数组的数组项初始化@ObjectLink
ViewA({ label: `ViewA this.arrA[first]`, a: this.arrA[0] })
ViewA({ label: `ViewA this.arrA[last]`, a: this.arrA[this.arrA.length-1] })
Button(`ViewB: reset array`)
.onClick(() => {
this.arrA = [new ClassA(0), new ClassA(0)];
})
Button(`ViewB: push`)
.onClick(() => {
this.arrA.push(new ClassA(0))
})
Button(`ViewB: shift`)
.onClick(() => {
this.arrA.shift()
})
Button(`ViewB: chg item property in middle`)
.onClick(() => {
this.arrA[Math.floor(this.arrA.length / 2)].c = 10;
})
Button(`ViewB: chg item property in middle`)
.onClick(() => {
this.arrA[Math.floor(this.arrA.length / 2)] = new ClassA(11);
})
}
}
}
这个示例中,ViewB
中的事件句柄对this.arrA
的修改会触发相应的更新,而ViewA
中的事件句柄则触发@ObjectLink
变量的修改,进而刷新相应的UI组件。
3. 二维数组
使用@Observed
观察二维数组的变化。可以声明一个被@Observed
装饰的继承Array的子类。
@Observed
class StringArray extends Array<String> {
}
通过使用new StringArray()
来构造StringArray
的实例,new
运算符使得@Observed
生效,能够观察到StringArray
的属性变化。
@Entry
@Component
struct IndexPage {
@State arr: Array<StringArray> = [new StringArray(), new StringArray(), new StringArray()];
build() {
Column() {
// ...
}
}
}
在上述示例中,对this.arr[0][0]
的修改会触发相应的更新。
持续优化和注意事项
持续优化
ARKTS的@Observed
和@ObjectLink
装饰器为处理嵌套类对象属性变化提供了强大的工具,但在实际应用中,为了保持代码的可读性和可维护性,我们还可以进行一些持续优化:
-
类型定义清晰: 在声明类和变量时,始终清晰地定义类型。这有助于提高代码的可读性,并使编辑器能够提供更好的代码提示。
// 清晰的类型定义 @ObjectLink public objLink: ExampleClass; // 避免使用any等模糊类型 public objLink: any;
-
模块化设计: 将代码模块化,按照功能或业务逻辑划分为小块,使得每个模块的职责清晰。这有助于降低复杂度,并能更容易地进行单元测试。
-
良好的命名规范: 使用清晰、有意义的命名规范,以便其他开发者能够理解你的代码。这对于嵌套结构尤为重要,因为清晰的命名有助于理解每个层级的含义。
注意事项
虽然@Observed
和@ObjectLink
提供了方便的工具来处理嵌套对象的属性变化,但在使用过程中,还需要注意一些潜在的问题:
-
性能考虑: 在处理大型数据结构时,观察每个属性的变化可能会导致性能开销。在实际应用中,需要评估性能并根据需要进行优化。
-
循环引用: 当多个对象互相引用时,要小心可能导致的循环引用问题。循环引用可能导致数据更新的不稳定性。
-
谨慎使用@Observed: 在使用
@Observed
装饰器时要谨慎,因为它会改变类原型链。确保了解其对原有代码和其他装饰器的影响。 -
避免滥用@ObjectLink: 不要在每个可能的地方都使用
@ObjectLink
,而是根据需要选择性地使用,以避免建立过于复杂的数据绑定关系。 -
清晰的数据流: 尽量保持清晰的数据流,避免过于复杂的嵌套关系,以便更容易追踪和调试代码。
综上所述,@Observed
和@ObjectLink
是强大的工具,但在使用时需要谨慎考虑性能和代码质量。合理的设计和良好的开发实践将有助于更好地利用这些工具,提高应用的可维护性和性能。
结语
通过使用@Observed
和@ObjectLink
装饰器,ARKTS提供了一种强大的机制来观察和处理嵌套类对象的属性变化,使得在实际应用开发中更容易管理复杂的数据结构。这两个装饰器的引入为开发者提供了更多灵活性和便利性,同时也需要谨慎使用以避免潜在的问题。在实际应用中,根据具体场景选择合适的装饰器将有助于提高开发效率和代码可维护性。
- 点赞
- 收藏
- 关注作者
评论(0)