为什么需要更强的状态管理

界面简单时,一个 @State 就够了。可一旦状态要跨组件传递、要放进独立类里管理,旧的装饰器组合就开始绕——谁该持有、谁该同步、谁改了谁刷新,全靠人肉记。状态管理 V2 的目标就是把这件事讲清楚:数据从哪来、谁能改、改了谁刷新。

状态管理的核心问题只有一个:状态变化如何自动、准确地传导到依赖它的界面。

这篇顺着装饰器到数据代理,把鸿蒙的响应式模型讲透。

从 @State 到状态管理 V2

@State 管视图内部的简单值。当状态是一个对象、要在父子组件间流动,就需要把整个对象做成可观测。V2 提供更简洁的数据代理写法,让普通类自动获得响应式能力,不用一层层套旧装饰器。

@ObservedV2
class Cart {
  @Trace var count: number = 0
  @Trace var total: number = 0
}

标注之后,count、total 变成可被界面追踪的属性。

@Observed 与 @ObjectLink

旧版里,一个类用 @Observed 标注,子组件用 @ObjectLink 接住它的实例。这样父组件持有对象,子组件引用同一个对象,任一属性变化都能触发两端刷新。它是跨组件共享对象的经典组合。

装饰器速查
  • @State视图内部私有状态。
  • @Prop父到子单向复制。
  • @Link父子双向同步。
  • @Observed/@ObjectLink共享对象引用。

@Prop 与 @Link 的边界

@Prop 是值的拷贝:子组件改自己的副本,不影响父级。@Link 是双向绑定:子组件改,父级跟着变。选错就会出现"改了界面不更新"或"误改了父状态"的诡异 bug。传基本类型、子只读用 @Prop;要回写用 @Link。

鸿蒙状态管理示意:中央一个发光立方体作为状态源,多根发光数据流线分流到周围抽象窗口卡片
状态源:一个可观测对象,向多个界面分流数据。

跨层级共享:@Provide/@Consume

状态要跨很深的层级传,一层层 props 太啰嗦。@Provide 在祖先组件提供值,@Consume 在后代任意层级直接取用,省去中间组件透传。适合主题、用户信息这类全局共享。

代价是数据流变得隐式——看单个组件看不出值从哪来,调试时要往上翻提供方。全局东西才用它,局部状态还是显式传。