鸿蒙开发 - 状态管理之@Observed和@ObjectLink
2023-12-25 15:32:13
@State
、@Prop
、@Link
、@Provide
等装饰器仅能观察到第一层的变化,但是在实际应用开发中,应用会根据开发需要,封装自己的数据模型。对于多层嵌套的情况,比如二维数组,或者数组项class,或者class
的属性是class
,他们的第二层的属性变化是无法观察到的。这就引出了@Observed/@ObjectLink
装饰器。
概述
@ObjectLink
和@Observed
类装饰器用于在涉及嵌套对象或数组的场景中进行双向数据同步:
- 被
@Observed
装饰的类,可以被观察到属性的变化; - 子组件中
@ObjectLink
装饰器装饰的状态变量用于接收@Observed
装饰的类的实例,和父组件中对应的状态变量建立双向数据绑定。这个实例可以是数组中的被@Observed
装饰的项,或者是class object
中的属性,这个属性同样也需要被@Observed
装饰。 - 单独使用
@Observed
是没有任何作用的,需要搭配@ObjectLink
或者@Prop
使用。
限制条件
- 使用
@Observed
装饰class
会改变class
原始的原型链,@Observed
和其他类装饰器装饰同一个class
可能会带来问题。 @ObjectLink
装饰器不能在@Entry
装饰的自定义组件中使用。
装饰器说明
@Observed类装饰器 | 说明 |
---|---|
装饰器参数 | 无 |
类装饰器 | 装饰class。需要放在class的定义前,使用new创建类对象。 |
@ObjectLink变量装饰器 | 说明 |
---|---|
装饰器参数 | 无 |
同步类型 | 不与父组件中的任何类型同步变量。 |
允许装饰的变量类型 | 必须为被@Observed装饰的class实例,必须指定类型。不支持简单类型,可以使用@Prop。@ObjectLink的属性是可以改变的,但是变量的分配是不允许的,也就是说这个装饰器装饰变量是只读的,不能被改变。 |
被装饰变量的初始值 | 不允许。 |
// 允许@ObjectLink装饰的数据属性赋值
this.objLink.a= ...
// 不允许@ObjectLink装饰的数据自身赋值
this.objLink= ...
说明
@ObjectLink
装饰的变量不能被赋值,如果要使用赋值操作,请使用@Prop
。
- @Prop装饰的变量和数据源的关系是是单向同步,@Prop装饰的变量在本地拷贝了数据源,所以它允许本地更改,如果父组件中的数据源有更新,@Prop装饰的变量本地的修改将被覆盖;
- @ObjectLink装饰的变量和数据源的关系是双向同步,@ObjectLink装饰的变量相当于指向数据源的指针。如果一旦发生@ObjectLink装饰的变量的赋值,则同步链将被打断。
变量的传递/访问规则说明
@ObjectLink传递/访问 | 说明 |
---|---|
从父组件初始化 | 必须指定。初始化@ObjectLink装饰的变量必须同时满足以下场景:类型必须是@Observed装饰的class。初始化的数值需要是数组项,或者class的属性。同步源的class或者数组必须是@State,@Link,@Provide,@Consume或者@ObjectLink装饰的数据。 |
与源对象同步 | 双向。 |
可以初始化子组件 | 允许,可用于初始化常规变量、@State、@Link、@Prop、@Provide |
初始化规则图示
观察变化和行为表现
观察的变化
@Observed
装饰的类,如果其属性为非简单类型,比如class
、Object
或者数组,也需要被@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;
}
}
以上示例中,ClassB被@Observed装饰,其成员变量的赋值的变化是可以被观察到的,但对于ClassA,没有被@Observed装饰,其属性的修改不能被观察到。
@ObjectLink b: ClassB
// 赋值变化可以被观察到
this.b.a = new ClassA(5)
this.b.b = 5
// ClassA没有被@Observed装饰,其属性的变化观察不到
this.b.a.c = 5
@ObjectLink:@ObjectLink只能接收被@Observed装饰class的实例,可以观察到:
- 其属性的数值的变化,其中属性是指Object.keys(observedObject)返回的所有属性,示例请参考嵌套对象。
- 如果数据源是数组,则可以观察到数组item的替换,如果数据源是class,可观察到class的属性的变化,示例请参考对象数组。
框架行为
1.初始渲染:
- @Observed装饰的class的实例会被不透明的代理对象包装,代理了class上的属性的setter和getter方法
- 子组件中@ObjectLink装饰的从父组件初始化,接收被@Observed装饰的class的实例,@ObjectLink的包装类会将自己注册给@Observed class。
2.属性更新:当@Observed装饰的class属性改变时,会走到代理的setter和getter,然后遍历依赖它的@ObjectLink包装类,通知数据更新。
文章来源:https://blog.csdn.net/SSY_1992/article/details/135133725
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!