本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
一、核心概念与设计目的
1.1 设计背景
@Observed和@ObjectLink是ArkUI框架中专门用于处理嵌套对象属性变化的状态管理装饰器组合。它们解决了传统状态管理在复杂对象结构中的局限性,特别是在多层嵌套对象属性变更时的UI同步问题。
1.2 核心功能定位
- @Observed: 类装饰器,用于标记一个类为可观察类,使其具备被观察的能力
- @ObjectLink: 变量装饰器,用于建立与@Observed装饰的类实例的属性级双向绑定
- 协同作用: 两者配合使用,实现对嵌套对象内部属性变化的精确监听和UI同步
二、版本支持与兼容性
| 版本 | 支持情况 |
|---|---|
| API version 9+ | 支持在ArkTS卡片中使用 |
| API version 11+ | 支持在元服务中使用 |
| 未来版本 | 持续增强对复杂数据类型的支持 |
三、装饰器详细说明
3.1 @Observed类装饰器
| 属性 | 说明 |
|---|---|
| 装饰器参数 | 无 |
| 同步类型 | 属性级双向同步 |
| 允许装饰的类型 | 自定义类 |
| 不允许装饰的类型 | 基本类型(string、number、boolean等) |
| 初始值 | 无需初始化 |
使用要求:
- 必须装饰整个类,而不是类的某个属性
- 类的属性变更需要通过赋值操作触发
- 支持继承,子类会自动继承@Observed特性
3.2 @ObjectLink变量装饰器
| 属性 | 说明 |
|---|---|
| 装饰器参数 | 无 |
| 同步类型 | 属性级双向同步 |
| 允许装饰的变量类型 | 被@Observed装饰的类实例 |
| 不允许装饰的变量类型 | 非@Observed装饰的类实例 |
| 初始值 | 必须从父组件初始化 |
初始化要求:
- 必须从父组件初始化
- 不支持本地初始化
- 必须通过构造函数参数传递
绑定特性:
- 建立与源对象的属性级绑定
- 支持深层嵌套属性的同步
- 避免不必要的深拷贝,提升性能
备注:@ObjectLink装饰器不能在@Entry装饰的自定义组件中使用。
四、与相关装饰器的对比
4.1 与@Prop的对比
| 特性 | @ObjectLink | @Prop |
|---|---|---|
| 同步机制 | 属性级双向同步 | 单向同步 |
| 内存使用 | 共享引用,内存占用低 | 深拷贝,内存占用高 |
| 性能表现 | 高性能,避免不必要的拷贝 | 性能较差,需要深拷贝 |
| 嵌套支持 | 支持深层嵌套,无层级限制 | 建议不超过5层嵌套 |
| 适用场景 | 需要修改嵌套对象属性 | 只需要读取数据 |
4.2 与@State/@Link的对比
| 特性 | @ObjectLink | @State/@Link |
|---|---|---|
| 同步粒度 | 属性级别 | 对象级别 |
| 更新机制 | 只更新变化的属性 | 更新整个对象 |
| 性能优化 | 精确更新,性能更优 | 整体更新,可能造成不必要的渲染 |
| 使用复杂度 | 需要配合@Observed使用 | 直接使用 |
五、基础使用示例
// 定义被观察的类
@Observed
class User {
name: string
age: number
address: Address
constructor(name: string, age: number, address: Address) {
this.name = name
this.age = age
this.address = address
}
}
@Observed
class Address {
city: string
street: string
constructor(city: string, street: string) {
this.city = city
this.street = street
}
}
// 父组件
@Entry
@Component
struct Parent {
@State user: User = new User('Alice', 25, new Address('Beijing', 'Main St'))
build() {
Column() {
Text(`User: ${this.user.name}, ${this.user.age}`)
Text(`Address: ${this.user.address.city}, ${this.user.address.street}`)
Child({ user: this.user })
}
}
}
// 子组件
@Component
struct Child {
@ObjectLink user: User
build() {
Column() {
Button('Increase Age')
.onClick(() => {
this.user.age += 1 // 直接修改属性,会同步到父组件
})
Button('Change Address')
.onClick(() => {
this.user.address.city = 'Shanghai' // 嵌套属性修改也会同步
})
}
}
}
六、观察变化机制
6.1 支持的变更类型
基本类型属性变更:
- string、number、boolean值的直接赋值
- enum值的变更
对象属性赋值:
- 整个对象的重新赋值
- 对象引用的变更
数组操作:
- 数组项的赋值修改
- push()、pop()、splice()等数组方法调用
- 数组长度的变更
集合类型操作:
- Map的set()、delete()、clear()操作
- Set的add()、delete()、clear()操作
6.2 变更检测机制
属性访问器重写: @Observed会重写类的属性访问器,在属性被修改时触发通知机制
变更传播:
- 属性变更 → 通知@ObjectLink装饰的变量 → 触发UI更新
- 支持嵌套属性的变更传播
批量更新优化:
- 在同一执行上下文中多次修改只会触发一次UI更新
- 避免不必要的重复渲染
693

被折叠的 条评论
为什么被折叠?



