HarmonyOS ArkTS学习-状态管理-@Observed和@ObjectLink
·
HarmonyOS ArkTS学习-状态管理-@Observed和@ObjectLink
参加文献
使用场景
@Observed和@ObjectLink用于嵌套对象的双向数据同步。
@Observed用于装饰类。
@ObjectLink用于装饰对象的属性。
@State的局限
@Sate可以检测到装饰对象的变化,但是无法检测到嵌套的属性变化。代码示例如下:
//@Observed和@ObjectLink嵌套类对象属性变化
//在这个用例中 说明@State不能同步嵌套的属性
class AClass{
public a: number;
public obj:BClass;
constructor(a:number,obj:BClass) {
this.a = a;
this.obj=obj;
}
}
class BClass{
public b:string;
constructor(b:string) {
this.b = b;
}
}
@Entry
@Component
struct Main{
objB:BClass = new BClass('hello');
@State objA:AClass = new AClass(10,this.objB);
build(){
Row(){
Column(){
Text(`objA.a = ${this.objA.a}`)
.fontSize(30)
Text(`objA.obj.b = ${this.objA.obj.b}`)
.fontSize(30)
Text(`objB.b = ${this.objB.b}`)
Button('set objA.a')
.onClick(()=>{
// this.objA.a = this.objA.a == 10 ? 100:10
console.log(`a = ${this.objA.a}`);
if(this.objA.a == 10){
this.objA.a = 100
}else{
this.objA.a = 10
}
})
Button('set objA.obj.b')
.onClick(()=>{
console.log(`b = ${this.objA.obj.b}`);
if(this.objA.obj.b == 'hello'){
this.objA.obj.b = 'good bye'
}else{
this.objA.obj.b = 'hello'
}
})
Button('set objB.b')
.onClick(()=>{
console.log(`b = ${this.objB.b}`);
if(this.objB.b == 'hello'){
this.objB.b = 'good bye'
}else{
this.objB.b = 'hello'
}
})
}
}
}
}
在上述示例中按钮set objA.a点击之后会改变Text(objA.a)的值的内容。但是按钮set objA.obj.b和set objB.b点击之后均不会使得Text中的值变化。但是通过日志可看出objB对象的b属性确实发生了变化:
06-05 00:46:13.449 I A0c0d0/JSApp: app Log: a = 10
06-05 00:46:14.185 I A0c0d0/JSApp: app Log: a = 100
06-05 00:46:15.455 I A0c0d0/JSApp: app Log: b = hello
06-05 00:46:16.114 I A0c0d0/JSApp: app Log: b = good bye
06-05 00:46:16.773 I A0c0d0/JSApp: app Log: b = hello
06-05 00:46:17.395 I A0c0d0/JSApp: app Log: b = good bye
@Observed和@ObjectLink监听嵌套属性的变化
//@Observed和@ObjectLink嵌套类对象属性变化
class AClass{
public a: number;
public obj:BClass;
constructor(a:number,obj:BClass) {
this.a = a;
this.obj=obj;
}
}
@Observed
class BClass{
public b:string;
constructor(b:string) {
this.b = b;
}
}
@Entry
@Component
struct Main{
objB:BClass = new BClass('hello');
@State objA:AClass = new AClass(10,this.objB);
build(){
Row(){
Column(){
Child({objB:this.objA.obj})
Button('set objA.obj.b')
.onClick(()=>{
if(this.objA.obj.b == 'hello'){
this.objA.obj = new BClass('good bye');
}else{
this.objA.obj = new BClass('hello');
}
})
}
}
}
}
@Component
struct Child{
//被@ObjectLink装饰的变量是不允许重新赋值为新对象的
@ObjectLink objB:BClass;
build(){
Row(){
Column(){
Text(`objB.b in child = ${this.objB.b}`)
.fontSize(30)
Button('set objB.b')
.onClick(()=>{
console.log(`a = ${this.objB.b}`);
if(this.objB.b == 'hello'){
//允许
this.objB.b = 'good bye'
//不允许
// this.objB = new BClass('gg')
}else{
this.objB.b = 'hello'
}
})
}
}
}
}
上述代码组件Child中声明了一个Text用于显示objB的b属性。此时父组件的set objA.obj.b和子组件中的set objB.b点击之后都会改变Text的值。注意到子组件中objB变量被@ObjectLink装饰,且BClass被@Observed装饰。被@Observed装饰的类,表明该类的属性变化可被观察。而被@ObjectLink装饰的表明该变量可被观察。所以只使用@Observed是无效的,必须搭配@ObjectLink或者@Prop使用。
使用限制
@ObjectLink装饰器不能在@Entry装饰的自定义组件中使用。
被@ObjectLink装饰的变量是不允许被更改的(参考上方代码示例中Child组件中的内容)。
备注
@Observed和@ObjectLink不仅可以用来处理嵌套对象的情况,也可以用于处理数组。详情可见:
官方文档中的代码示例
更多推荐

所有评论(0)