@State 与 @Observed:HarmonyOS 状态管理到底怎么选
·
@State 与 @Observed:HarmonyOS 状态管理到底怎么选
前言
状态管理是 ArkUI 开发的地基。很多开发者分不清 @State 和 @Observed 的边界,结果"对象里的字段改了界面不刷新",或"为了一个嵌套属性把整个对象都标记响应式"导致性能浪费。本文基于论坛问题「@State 与 @Observed 在状态管理上该如何」,把二者的职责边界和组合用法讲透。
问题描述
- 用
@State装了一个对象,修改obj.field后界面没刷新; - 嵌套对象(对象里的对象)属性变化无法被感知;
- 子组件想观察父传来的对象内部变化,不知道用什么装饰器;
- 听说
@Observed很强大,于是到处用,反而拖慢渲染。
细节解析
1. @State:组件私有状态,只认"整体替换"
@State 管理组件自身的状态。@State obj: MyObj 只有在 obj 这个引用被整体替换时才触发刷新;修改 obj.a.b 这种深层字段,框架并不知道,因此不刷新。它适合基础类型或"整块数据换新"的场景。
2. @Observed + @ObjectLink:观察嵌套对象内部
要让嵌套对象内部属性的变化也驱动 UI,需要:
- 用
@Observed装饰那个 class(可多层嵌套,每层都要标); - 在消费该对象的子组件里用
@ObjectLink接收。
@ObjectLink 指向的是父组件里 @State/@Link 持有的同一个对象引用,因此对象内部字段变化能精确通知到用了它的子组件。
3. V1 与 V2 的对应关系
- V1:
@State+@Observed+@ObjectLink(本文示例); - V2:
@Local+@ObservedV2+@Trace(更细粒度,只刷新被@Trace标记的属性)。
4. 选择原则
- 基础类型 / 整体替换的对象 →
@State(V2 用@Local); - 需要观察对象内部属性、且跨多组件共享该对象 →
@Observed+@ObjectLink; - 不要为了"能用"就给所有对象套
@Observed,只在确实要观察内部变化时才用。
示例代码(V1)
@Observed
class Address {
city: string = 'Beijing';
street: string = 'Main St';
}
@Observed
class User {
name: string = 'Tom';
addr: Address = new Address(); // 嵌套对象也要 @Observed
}
// 父组件
@Entry @Component
struct Parent {
@State user: User = new User();
build() {
Column() {
Button('改城市').onClick(() => { this.user.addr.city = 'Shanghai'; })
Child({ user: this.user })
}
}
}
// 子组件:用 @ObjectLink 观察同一对象引用
@Component
struct Child {
@ObjectLink user: User;
build() {
Column() {
Text('姓名:' + this.user.name)
Text('城市:' + this.user.addr.city) // 父改 city 这里会刷新
}
}
}
总结
@State管"整体换",@Observed+@ObjectLink管"内部变";- 嵌套对象每一层都要
@Observed,否则深层不刷新; - 改
obj.field不刷新 → 正是@State的边界,换@Observed组合即可; - V2 用
@Local/@ObservedV2/@Trace实现更精准的属性级刷新。
选对装饰器,既能保证刷新正确,又能避免无谓的性能开销。
更多推荐



所有评论(0)