【HarmonyOS 状态管理超全解析】从 V1 到 V2,一次讲清 @State/@Observed/@Local…等所有装饰器!附超易懂示例!

如果你刚接触 HarmonyOS ArkUI,第一次看到各种装饰器时可能会有这样的心情:

"哇,这么多 @ 注解,都是什么鬼?能不能不要这么复杂?"

别慌! 其实它们一点也不难。你把 UI 组件想象成一个个小房间,把状态装饰器想象成房间里的"家具"、"窗户"、"储物柜",就会发现它们非常好理解。

本文将用最轻松幽默的方式 ,把 状态管理 V1 和 V2 全系列装饰器一网打尽,帮你一次读懂!


一、为什么需要状态管理?

简单一句话:

状态管理决定你的 UI 长什么样、什么时候更新,以及组件之间怎么传递数据。

举个简单例子:

你有一个计数器按钮,点一下数字加一。数字就是 状态,只有状态变了,UI 才会更新。

所以我们需要告诉系统:

  • 哪些变量是状态?
  • 谁可以读?
  • 谁可以改?
  • 改了要不要通知别人?
  • 能不能共享给其他组件?

这就是各种装饰器存在的意义!


二、状态管理 V1(旧体系)

HarmonyOS 早期的状态管理体系,主要包括:

  • @State
  • @Prop
  • @Link
  • @Observed
  • @ObjectLink
  • @Provide / @Consume
  • @Watch

我们用大白话讲,保证你马上懂。


1. @State ------ 我自己的状态,我自己改

组件内部自己维护、自己改动的数据。

就像房间里的闹钟,别人碰不到,只有我能调。

示例
typescript 复制代码
@Entry
@Component
struct CounterPage {
  @State count: number = 0;

  build() {
    Column() {
      Button(`点击次数:${this.count}`)
        .onClick(() => {
          this.count++; // 自动触发 UI 更新
        })
    }
  }
}

作用: 组件内部使用,修改后自动刷新 UI。


2. @Prop ------ 父给我的"只读礼物"

只能父组件给,子组件可以修改但不会影响父组件

重要修正: @Prop 子组件可以修改,但修改只在子组件内生效,不会回传给父组件。

示例

父组件:

typescript 复制代码
@Entry
@Component
struct Parent {
  @State name: string = "张三";

  build() {
    Column() {
      Text(`父组件:${this.name}`)
      ChildComp({ name: this.name })
    }
  }
}

子组件:

typescript 复制代码
@Component
struct ChildComp {
  @Prop name: string;

  build() {
    Column() {
      Text(`你好,${this.name}`)
      Button('改名')
        .onClick(() => {
          this.name = "李四"; // 只在子组件生效
        })
    }
  }
}

父组件给子组件同一个变量的引用,谁改都会同步。

就像你和室友共用一个 WiFi 密码,谁改了密码,两个人一起受影响。

示例

父组件:

typescript 复制代码
@Entry
@Component
struct Parent {
  @State count: number = 0;

  build() {
    Column() {
      Text(`父组件 count: ${this.count}`)
      ChildComp({ count: this.count }) // 使用 $ 传递引用
    }
  }
}

子组件:

typescript 复制代码
@Component
struct ChildComp {
  @Link count: number;

  build() {
    Button(`子组件 count: ${this.count}`)
      .onClick(() => this.count++)
  }
}

父子都会同步 UI!


4. @Observed ------ 观察对象的属性变化

用于"对象类型"的监听,必须配合 @ObjectLink 使用才能让对象内部字段变化更新 UI。

重要修正: @Observed 是类装饰器,不是用在属性上。

示例
typescript 复制代码
@Observed
class Person {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

@Entry
@Component
struct Parent {
  @State person: Person = new Person("张三", 18);

  build() {
    Column() {
      Text(`${this.person.name}, ${this.person.age}岁`)
      ChildComp({ person: this.person })
    }
  }
}

必须与 @Observed 配合使用。

示例

子组件:

typescript 复制代码
@Component
struct ChildComp {
  @ObjectLink person: Person;

  build() {
    Button("长大一岁")
      .onClick(() => {
        this.person.age++; // 父子组件都会更新
      })
  }
}

6. @Provide / @Consume ------ 全局共享状态(依赖注入)

像一个大仓库,所有组件都能拿共享数据。

适用于"登录状态""主题"等全局信息。

示例

上层组件:

typescript 复制代码
@Entry
@Component
struct Root {
  @Provide theme: string = "dark";

  build() {
    Column() {
      GrandChild()
    }
  }
}

孙子组件随处可取:

typescript 复制代码
@Component
struct GrandChild {
  @Consume theme: string;

  build() {
    Text(`当前主题: ${this.theme}`)
  }
}

7. @Watch ------ 监听变量变化回调

状态改变时触发一个方法。

示例
typescript 复制代码
@Component
struct CounterComp {
  @State @Watch("onCountChange") count: number = 0;

  onCountChange() {
    console.log("count变啦!", this.count);
  }

  build() {
    Button(`${this.count}`)
      .onClick(() => this.count++)
  }
}

V1 小结

如果用一句话总结:

V1 的状态管理功能完整但相对分散,在大型项目中容易出现管理混乱。


为什么有了 V1 还要开发 V2?

V1 的痛点

  1. 装饰器过多,概念分散

    • @State、@Prop、@Link、@Provide、@Consume、@Observed、@ObjectLink...新手容易混淆
  2. 对象观测不够智能

    • @Observed + @ObjectLink 的配合使用比较繁琐
    • 嵌套对象的深度监听支持不够好
  3. 性能优化困难

    • 没有明确的组件复用机制
    • 缺少计算属性等现代框架常见特性
  4. 类型安全不足

    • 在 TypeScript 环境下类型推导不够友好
  5. 与现代前端框架理念脱节

    • 缺少类似 Vue 的 computed、React 的 useMemo 等特性
    • 事件回调传递不够优雅

V2 的优势

  1. 统一的状态管理模型 - 基于 @ObservedV2 的统一可观测对象
  2. 更好的类型支持 - 完善的 TypeScript 类型推导
  3. 性能优化内置 - @ReusableV2、@Computed 等性能优化装饰器
  4. 现代化 API 设计 - @Event 事件回调、@Monitor 监听等更符合现代开发习惯
  5. 更易维护 - 代码结构更清晰,大型项目更好管理

简单说:V2 是吸取了 V1 的经验教训,参考了 Vue、React 等现代框架的优秀设计,打造的新一代状态管理体系。


三、状态管理 V2(新体系,全新的统一语法)

HarmonyOS Next 开始推出 V2 状态管理体系,目标是:

  • 更统一
  • 更清晰
  • 写法更简洁
  • 更容易维护大型项目

V2 的主要装饰器有:

  • @ComponentV2
  • @ObservedV2
  • @Local
  • @Param
  • @Once
  • @Event
  • @Provider / @Consumer
  • @Monitor
  • @Computed
  • @Type
  • @Require

1. @ComponentV2 ------ 定义组件的新方式

V2 必须用这个来声明组件。

typescript 复制代码
@ComponentV2
struct MyComp {
  build() {
    Text("Hello V2")
  }
}

可以理解为新版的 @Component


2. @ObservedV2 ------ 可观察数据源(V2 核心)

类装饰器,用于定义可观察的数据模型类。

类似传统框架里的 Model,对象内属性改变 UI 自动更新。

示例
typescript 复制代码
@ObservedV2
class CounterModel {
  count: number = 0;
  name: string = "计数器";
}

在组件中使用:

typescript 复制代码
@ComponentV2
struct Counter {
  model: CounterModel = new CounterModel();

  build() {
    Column() {
      Text(`${this.model.name}: ${this.model.count}`)
      Button("加一")
        .onClick(() => this.model.count++)
    }
  }
}

3. @Local ------ 本地状态(类似 V1 的 @State)

组件自己的状态,只在当前组件存在。

typescript 复制代码
@ComponentV2
struct MyComp {
  @Local value: number = 0;

  build() {
    Text(`${this.value}`)
  }
}

4. @Param ------ 父组件传来的参数(类似 @Prop)

typescript 复制代码
@ComponentV2
struct ChildComp {
  @Param title: string = "";

  build() {
    Text(this.title)
  }
}

5. @Once ------ 只初始化一次的参数

用于父组件传递但不希望后续更新的参数。

typescript 复制代码
@ComponentV2
struct ChildComp {
  @Once id: string = "";

  build() {
    Text(`ID: ${this.id}`)
  }
}

6. @Event ------ 子向父回调事件

类似 Web 中的事件回调 function prop,这是 V2 的一大亮点!

示例

父组件:

typescript 复制代码
@ComponentV2
struct Parent {
  @Local count: number = 0;

  build() {
    Child({ onAdd: () => this.count++ })
  }
}

子组件:

typescript 复制代码
@ComponentV2
struct Child {
  @Event onAdd: () => void = () => {};

  build() {
    Button("加一")
      .onClick(() => this.onAdd())
  }
}

非常优雅!


7. @Provider / @Consumer ------ 依赖注入(V2 延续)

注意 V2 中是 @Consumer 不是 @Consume

typescript 复制代码
@ComponentV2
struct Root {
  @Provider theme: string = "dark";

  build() {
    GrandChild()
  }
}

@ComponentV2
struct GrandChild {
  @Consumer theme: string = "";

  build() {
    Text(`主题: ${this.theme}`)
  }
}

8. @Monitor ------ 监控字段变化(类似 V1 的 @Watch)

typescript 复制代码
@ComponentV2
struct Counter {
  @Local count: number = 0;

  @Monitor("count")
  onCountChange() {
    console.log("count changed!", this.count);
  }

  build() {
    Button(`${this.count}`)
      .onClick(() => this.count++)
  }
}

9. @Computed ------ 派生属性(自动计算)

跟 Vue 的 computed 一样:

示例
typescript 复制代码
@ComponentV2
struct Calculator {
  @Local num: number = 10;

  @Computed
  get double(): number {
    return this.num * 2;
  }

  build() {
    Column() {
      Text(`数字: ${this.num}`)
      Text(`双倍: ${this.double}`)
      Button("加一")
        .onClick(() => this.num++)
    }
  }
}

num 改变时,double 自动更新!


10. @Type ------ 标注复杂类型

主要用于数组、集合等复杂类型的观测。

typescript 复制代码
@ObservedV2
class DataModel {
  @Type(Person)
  users: Person[] = [];
}

11. @Require ------ 必传参数

用于标记组件的必传属性。

typescript 复制代码
@ComponentV2
struct UserCard {
  @Require @Param name: string = "";

  build() {
    Text(this.name)
  }
}

四、V1 和 V2 的对照表(超清晰)

作用 V1 V2
本地状态 @State @Local
父传子(可变) @Prop @Param
父传子(不变) - @Once
双向绑定 @Link -(推荐使用 @ObservedV2 模型)
可观察对象 @Observed/@ObjectLink @ObservedV2
事件回调 普通函数传递 @Event
监听字段 @Watch @Monitor
派生属性 - @Computed
全局共享 @Provide/@Consume @Provider/@Consumer
组件定义 @Component @ComponentV2
必传参数 - @Require
复杂类型 - @Type

五、写个完整 Demo(V2)

让你快速感受新体系的优雅。

typescript 复制代码
@ObservedV2
class TodoItem {
  title: string;
  done: boolean;

  constructor(title: string) {
    this.title = title;
    this.done = false;
  }
}

@ObservedV2
class TodoStore {
  @Type(TodoItem)
  todos: TodoItem[] = [];

  addTodo(title: string) {
    this.todos.push(new TodoItem(title));
  }
}

@ComponentV2
struct TodoApp {
  store: TodoStore = new TodoStore();
  @Local input: string = "";

  build() {
    Column() {
      Row() {
        TextInput({ placeholder: "输入待办事项" })
          .onChange((value) => this.input = value)
        Button("添加")
          .onClick(() => {
            this.store.addTodo(this.input);
            this.input = "";
          })
      }

      ForEach(this.store.todos, (item: TodoItem) => {
        Row() {
          Checkbox()
            .select(item.done)
            .onChange((checked) => item.done = checked)
          Text(item.title)
        }
      })
    }
  }
}

是不是清爽很多?


六、总结:如何形容 V1 和 V2?

如果让我用一句最形象的话总结:

  • V1 像一个装满了各种工具的工具箱,能用但比较分散,需要你记住每个工具的用法。
  • V2 像新装修后的智能家居系统,统一、自动、高效、好维护,更符合现代开发理念。

建议

  • 新项目: 优先使用 V2 状态管理体系
  • 老项目: 可以逐步迁移,V1 和 V2 可以在同一项目共存
  • 学习路径: 了解 V1 基础 → 重点掌握 V2 → 实战中深化理解

HarmonyOS 的状态管理正在变得越来越成熟和易用,希望这篇文章能帮你彻底理解这套体系!


🔥 如果觉得有帮助,别忘了点赞收藏哦!有问题欢迎评论区交流!

相关推荐
500843 小时前
鸿蒙 Flutter 隐私合规:用户授权中心与数据审计日志
flutter·华为·开源·wpf·音视频
威哥爱编程3 小时前
【鸿蒙开发案例篇】基于MindSpore Lite的端侧人物图像分割案例
harmonyos·arkts·arkui
我是Feri3 小时前
HarmonyOS 6.0 ArkWeb开发实战:从基础到进阶的ArkUI+ArkTS实践
华为·harmonyos·harmonyos6.0
乾元3 小时前
OSPF / BGP 自动化设计与错误避坑清单—— 控制平面是“算出来的”,不是“敲出来的”
运维·网络·人工智能·平面·华为·自动化
鸿蒙开发工程师—阿辉4 小时前
HarmonyOS 5 极致动效实验室:共享元素转场 (GeometryTransition)
华为·harmonyos
豫狮恒4 小时前
OpenHarmony Flutter 分布式软总线实战:跨设备通信的核心技术与应用
flutter·wpf·harmonyos
遇到困难睡大觉哈哈4 小时前
Harmony os —— Data Augmentation Kit 知识问答完整示例实战拆解(从 0 跑通流式 RAG)
harmonyos·鸿蒙
L、2185 小时前
Flutter 与 OpenHarmony 跨端融合新范式:基于 FFI 的高性能通信实战
flutter·华为·智能手机·electron·harmonyos
乾元5 小时前
从命令行到自动诊断:构建 AI 驱动的故障树与交互式排障机器人引言
运维·开发语言·网络·人工智能·华为·自动化