本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
一、@Trace
装饰器的作用
@Trace
是鸿蒙状态管理V2(ArkUI 3.0)中新增的装饰器,用于 标记类属性,实现以下功能:
- 精准监听:当被装饰的属性值变化时,仅触发依赖该属性的UI更新(避免V1中全量刷新的性能问题)。
- 嵌套对象支持:支持深度监听对象内部属性或数组元素的变化。
- 性能优化:与
@ObservedV2
配合使用,减少不必要的渲染。
二、@Trace
的使用
1. 基本用法(类属性监听)
@ObservedV2
class User {
@Trace name: string = 'Alice'; // 标记需监听的属性
@Trace age: number = 25;
}
@Entry
@ComponentV2
struct UserProfile {
@Local user: User = new User(); // 初始化状态
build() {
Column() {
Text(`Name: ${this.user.name}`).onClick(() => {
this.user.name = 'Bob'; // 仅更新Text组件
})
Text(`Age: ${this.user.age}`)
}
}
}
说明:
- 当
name
变化时,仅关联的Text
组件会重新渲染,age
相关的UI不受影响。
2. 嵌套对象监听
@ObservedV2
class Address {
@Trace city: string = 'Beijing';
@Trace street: string = 'Xinyuan';
}
@ObservedV2
class User {
@Trace address: Address = new Address();
}
@Entry
@ComponentV2
struct Profile {
@Local user: User = new User();
build() {
Column() {
Text(`City: ${this.user.address.city}`).onClick(() => {
this.user.address.city = 'Shanghai'; // 深度监听生效
})
}
}
}
3. 数组元素监听
@ObservedV2
class ShoppingCart {
@Trace items: string[] = ['Apple', 'Banana'];
}
@Entry
@ComponentV2
struct CartPage {
@Local cart: ShoppingCart = new ShoppingCart();
build() {
Column() {
ForEach(this.cart.items, (item: string) => {
Text(item).onClick(() => {
this.cart.items[0] = 'Orange'; // 触发数组元素更新
})
})
}
}
}
三、@Trace
与 @ObservedV2
的协作
@ObservedV2
:装饰类,使类具备可监听能力(类似V1的@Observed
,但支持深度监听)。@Trace
:装饰具体属性,明确指定需要跟踪的字段。
协作规则:
- 只有被
@ObservedV2
装饰的类中的@Trace
属性才会被监听。 - 若类未被
@ObservedV2
装饰,@Trace
不生效。
四、与V1版本的对比
特性 | V1(@Observed + @Prop/@Link) | V2(@ObservedV2 + @Trace) |
---|---|---|
监听粒度 | 仅类实例级别 | 属性级别(精准更新) |
嵌套支持 | 需手动实现深层监听 | 自动支持对象/数组内部变化 |
性能 | 可能触发多余渲染 | 最小化渲染范围 |
代码复杂度 | 高(需维护多个装饰器) | 低(声明式标记) |
五、注意事项
- 不可滥用:仅对需要响应式更新的属性使用
@Trace
,避免内存开销。 - 不可与
@State
混用:@Trace
用于装饰类属性,@State
用于组件内部状态。 - 类型限制:被
@Trace
装饰的属性需为可序列化类型(如string
、number
、object
等)。
六、完整示例
@ObservedV2
class FormData {
@Trace username: string = '';
@Trace password: string = '';
}
@Entry
@ComponentV2
struct LoginPage {
@Local form: FormData = new FormData();
build() {
Column() {
TextInput({ placeholder: 'Username' })
.onChange((value: string) => {
this.form.username = value; // 触发精准更新
})
TextInput({ placeholder: 'Password' })
.onChange((value: string) => {
this.form.password = value;
})
Button('Submit').onClick(() => {
console.log(this.form);
})
}
}
}