HarmonyOS鸿蒙Next中@Observed/@ObjectLink对嵌套对象使用的疑问
HarmonyOS鸿蒙Next中@Observed/@ObjectLink对嵌套对象使用的疑问
现在这个代码是有问题的,我点(父 修改深层城市) 或者 (子 修改年龄+城市)按钮,只有子组件里的内容发生了变化,父组件的 Text(父:${this.user.name} | ${this.user.profile.age} | ${this.user.profile.addr.city})没有变化,研究了半天也没理解这样为什么错了
// 第三层
[@Observed](/user/Observed)
class Address {
city: string;
constructor(city: string) {
this.city = city;
}
}
// 第二层
[@Observed](/user/Observed)
class Profile {
age: number;
addr: Address; // 嵌套下层对象
constructor(age: number, addr: Address) {
this.age = age;
this.addr = addr;
}
}
// 最外层
[@Observed](/user/Observed)
class User {
name: string;
profile: Profile; // 嵌套中层对象
constructor(name: string, profile: Profile) {
this.name = name;
this.profile = profile;
}
}
@Entry
@Component
struct Parent {
// 必须 @State 包裹 Observed 对象
@State user: User = new User("张三",
new Profile(20, new Address("北京"))
);
build() {
Column({ space: 20 }) {
Text(`父:${this.user.name} | ${this.user.profile.age} | ${this.user.profile.addr.city}`)
// 把 嵌套的成员对象 传给子
Child({
profile: this.user.profile,
addr: this.user.profile.addr
})
// 修改深层属性(不改变引用地址,只改内部值)
Button("父 修改深层城市")
.onClick(() => {
this.user.profile.addr.city = "上海";
console.log('11',JSON.stringify(this.user))
})
}
.padding(20)
}
}
@Component
struct Child {
// 接收第二层对象
[@ObjectLink](/user/ObjectLink) profile: Profile;
// 接收第三层嵌套对象
[@ObjectLink](/user/ObjectLink) addr: Address;
build() {
Column({ space: 10 }) {
Text(`子年龄:${this.profile.age}`)
Text(`子城市:${this.addr.city}`)
Button("子 修改年龄+城市")
.onClick(() => {
this.profile.age = 99;
this.addr.city = "广州";
})
}
.border({width:1})
.padding(10)
}
}
更多关于HarmonyOS鸿蒙Next中@Observed/@ObjectLink对嵌套对象使用的疑问的实战教程也可以访问 https://www.itying.com/category-93-b0.html
学习了
十分感谢,我明白了,我在父组件里state修饰的是user,所以我传对象给子元素的时候也必须传被state修饰的是user
为什么不变化:@Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化-管理组件拥有的状态-状态管理(V1)
解决方案采用V2:
// 第三层
@ObservedV2
class Address {
@Trace city: string;
constructor(city: string) {
this.city = city;
}
}
// 第二层
@ObservedV2
class Profile {
@Trace age: number;
@Trace addr: Address; // 嵌套下层对象
constructor(age: number, addr: Address) {
this.age = age;
this.addr = addr;
}
}
// 最外层
@ObservedV2
class User {
@Trace name: string;
@Trace profile: Profile; // 嵌套中层对象
constructor(name: string, profile: Profile) {
this.name = name;
this.profile = profile;
}
}
@Entry
@ComponentV2
struct Parent {
// 必须 @State 包裹 Observed 对象
@Local user: User = new User("张三",
new Profile(20, new Address("北京"))
);
build() {
Column({ space: 20 }) {
Text(`父:${this.user.name} | ${this.user.profile.age} | ${this.user.profile.addr.city}`)
// 把 嵌套的成员对象 传给子
Child({
profile: this.user.profile,
addr: this.user.profile.addr
})
// 修改深层属性(不改变引用地址,只改内部值)
Button("父 修改深层城市")
.onClick(() => {
this.user.profile.addr.city = "上海";
console.log('11', JSON.stringify(this.user))
})
}
.padding(20)
}
}
@ComponentV2
struct Child {
// 接收第二层对象
@Param @Require profile: Profile;
// 接收第三层嵌套对象
@Param @Require addr: Address;
build() {
Column({ space: 10 }) {
Text(`子年龄:${this.profile.age}`)
Text(`子城市:${this.addr.city}`)
Button("子 修改年龄+城市")
.onClick(() => {
this.profile.age = 99;
this.addr.city = "广州";
})
}
.border({ width: 1 })
.padding(10)
}
}
在HarmonyOS鸿蒙Next的ArkTS中,**@Observed用于装饰类,使其实例可被观察;@ObjectLink**用于父组件中引用被@Observed装饰的子对象,实现嵌套数据的双向同步。嵌套对象需每层均用@Observed装饰,数组内对象同样需@Observed,否则无法触发更新。@ObjectLink只能配合@Observed使用,不可用于普通对象或简单类型。
在 HarmonyOS Next 中,父组件 @State user 只能观测到 user 本身的第一层属性变化(例如 user.name 或 user 被整体替换),无法自动追踪深层嵌套对象的内部属性修改。
当执行 this.user.profile.addr.city = "上海" 时,user.profile 引用未变、addr 引用未变,仅 Address 的内部 city 变了,@State 感知不到这一变化,因此父组件的 Text 不会刷新。
而子组件通过 @ObjectLink 接收 Profile 和 Address 对象,这两个类均为 @Observed,@ObjectLink 会订阅该实例的属性变更,所以子组件正常刷新。
这是状态观察的深度限制:@State 仅浅层观察,@ObjectLink 直接绑定被观测实例可响应其任意深度属性修改。若需父组件同步更新,必须让父组件能感知到引用变化(例如替换 profile 对象)。



