《ArkTS 实战:@Observed 与 @ObjectLink 让嵌套对象状态实时刷新》
在鸿蒙 ArkTS 开发中,很多开发者都遇到过这样的困惑:用 @State 装了一个对象,改了对象里的某个字段,界面却纹丝不动。问题不在数据没改,而在状态观测的层级上——@State 只观测第一层属性的变化,嵌套对象的内部变化默认不会触发界面刷新。要解决这个问题,需要 @Observed 与 @ObjectLink 配合使用。
一、为什么只改嵌套字段不刷新
假设有一个用户信息对象,里面嵌套了一个地址对象。把整个用户信息对象声明为 @State 后,直接修改 user.name 可以刷新界面,因为 name 是 @State 对象的第一层属性;但修改 user.address.city 时,变化发生在第二层,@State 观测不到,界面也就不会更新。很多“数据改了界面没变”的问题,根源都在这里。
二、@Observed:让嵌套类变得可观测
给嵌套的类加上 @Observed 装饰器,就等于告诉 ArkTS:这个类的属性变化也需要被观测。注意 @Observed 修饰的类本身不持有状态,它必须配合 @State、@Link、@Prop、@ObjectLink 等状态装饰器一起使用,单独使用没有意义。
三、@ObjectLink:在子组件中观测嵌套对象
如果把嵌套对象传给子组件展示,子组件里要用 @ObjectLink 来接收,而不是 @Prop。@Prop 是单向数据同步,父组件改了嵌套对象,子组件未必能感知;而 @ObjectLink 与父组件的 @State 对象保持同步观测,嵌套属性一变,子组件立即刷新。
四、完整可运行示例
下面是一个可以直接放到 ArkTS 工程里运行的例子,点击按钮改名或搬家,界面会实时刷新:
@Observed
class Address {
city: string = '深圳'
district: string = '南山区'
constructor(city: string, district: string) {
this.city = city
this.district = district
}
}
@Observed
class UserProfile {
name: string = '开发者小明'
age: number = 28
address: Address = new Address('深圳', '南山区')
constructor(name: string, age: number) {
this.name = name
this.age = age
}
}
@Entry
@Component
struct ProfilePage {
@State profile: UserProfile = new UserProfile('开发者小明', 28)
build() {
Column({ space: 16 }) {
Text(`姓名:${this.profile.name}`)
Text(`年龄:${this.profile.age}`)
AddressView({ address: this.profile.address })
Button('改名').onClick(() => {
this.profile.name = '开发者小红'
})
Button('搬家到北京').onClick(() => {
this.profile.address.city = '北京'
this.profile.address.district = '海淀区'
})
}
.width('100%')
.padding(16)
}
}
@Component
struct AddressView {
@ObjectLink address: Address
build() {
Column({ space: 8 }) {
Text(`城市:${this.address.city}`)
Text(`城区:${this.address.district}`)
}
}
}
在这个例子里,UserProfile 和 Address 都加了 @Observed,父组件用 @State 持有整个 profile,子组件用 @ObjectLink 接收 address。点“搬家到北京”时,改的是第二层的 city 和 district,但因为两层都是可观测的,界面会立刻更新。
五、三个容易踩的坑
第一,嵌套类漏加 @Observed。只给外层加 @State、内层类没有 @Observed,是最常见的写法错误,改内层字段依然不刷新。
第二,子组件误用 @Prop 接收嵌套对象。@Prop 适合传基本类型或不需要回写的快照数据;要让子组件实时感知嵌套对象的变化,应该用 @ObjectLink。
第三,整体替换对象时要留意引用。如果直接给 @State 变量赋一个全新对象,第一层属性变化会触发刷新;但如果在子组件里持有旧对象的引用,旧引用不会自动指向新对象,必要时应在父组件层面重新传参。
六、小结
@State 管第一层,@Observed 让嵌套类可观测,@ObjectLink 让子组件同步观测嵌套对象。三者分工明确:数据结构嵌套多深,可观测装饰就要跟到多深。下次再遇到“数据改了界面没变”,先检查嵌套类有没有加 @Observed,再检查子组件是不是用了 @ObjectLink,问题往往就出在这两处。参考来源:HarmonyOS 官方文档中关于 ArkTS 状态管理的说明(@State、@Observed、@ObjectLink 的定义与使用约束)。
- 点赞
- 收藏
- 关注作者
评论(0)