当前位置:首页>鸿蒙APP>鸿蒙开发必看!⼀⽂搞懂HarmonyOS状态管理V2

鸿蒙开发必看!⼀⽂搞懂HarmonyOS状态管理V2

  • 2026-08-21 12:07:25
鸿蒙开发必看!⼀⽂搞懂HarmonyOS状态管理V2

本文系统讲解鸿蒙ArkUI状态管理V2,带你从入门到实战

大家好!今天要给大家分享的是鸿蒙开发中非常重要的状态管理。

我们在开发APP时,最常见的需求就是:数据变化时,UI要自动更新。比如:

  • 用户点击按钮,计数+1,数字要自动变化

  • 输入框输入文字,下面的列表要自动过滤

  • 删除一条数据,列表要自动少一条

这些看似简单的功能,在传统开发中需要手动编写大量代码。但有了状态管理V2,一切变得非常简单!

一、什么是状态管理?

1.1 生活中的例子

想象一下,你在餐厅点餐:

在这个过程中:

  • 你 = 用户(操作UI)

  • 点餐内容 = 状态(数据)

  • 服务员 = 状态管理系统(负责同步)

  • 做菜 = 业务逻辑处理

服务员(状态管理)把你的需求告诉厨房(数据层),厨房做好了自动端给你(UI自动更新),你不需要跑去厨房看菜做好了没有。

1.2 技术上的定义

状态管理 = 数据 + UI同步机制当数据变化时,UI自动更新,无需手动操作。

二、MVVM架构模式

在鸿蒙中,状态管理是基于MVVM架构模式实现的。

2.1 什么是MVVM?

2.2 数据流向

核⼼优势:数据驱动UI,开发者只需关注数据变化,UI⾃动更新! 

三、状态管理装饰器详解

鸿蒙状态管理V2提供了⼀系列强⼤的装饰器:

四、@Local: 组件内部状态

4.1 什么是@Local?

@Local 用于管理组件内部的状态。被它装饰的变量变化时,UI会自动更新。

4.2 基本语法

@Local 变量名:类型 = 初始值;

4.3 简单示例:计数器

@Entry@Componentstruct CounterPage {  @Local count: number = 0; // 定义状态  build() {    Column({ space: 20 }) {      // 显示计数 - 自动更新!      Text('当前计数: ' + this.count)        .fontSize(30)       // 按钮点击,状态变化      Button('点我+1')        .onClick(() => {          this.count++; // 状态变化,UI自动刷新        })    }  }}

4.4 效果展示

4.5 进阶:待办事项完成状态

@Entry@Componentstruct TaskDemo {  @Local isFinished: boolean = false; // 任务完成状态  build() {    Row({ space: 15 }) {      // 根据状态显示不同图标      Image(this.isFinished ?             $r('app.media.ic_checked') :             $r('app.media.ic_unchecked'))        .width(24)      // 任务文字 - 带删除线效果      Text('学习鸿蒙开发')        .fontSize(18)        .decoration({          type: this.isFinished ?                 TextDecorationType.LineThrough :                 TextDecorationType.None        })    }    .onClick(() => {      this.isFinished = !this.isFinished; // 点击切换    })  }}
五、@Param:⽗组件向⼦组件传数据

5.1 什么是@Param?

@Param 让⼦组件可以接收⽗组件传⼊的数据。实现⽗→⼦的单向数据流。 

5.2 基本语法

// 子组件接收@Componentstruct ChildComponent {  @Param 变量名:类型;      // 只读  @Param @Once 变量名:类型; // 可修改(仅初始化一次)}

5.3 示例:任务列表

// 子组件:任务项@Componentstruct TaskItem {  @Param taskName: string = '';          // 接收任务名称  @Param @Once isFinished: boolean = false; // 接收初始状态,可修改  build() {    Row({ space: 15 }) {      Image(this.isFinished ?             $r('app.media.ic_checked') :             $r('app.media.ic_unchecked'))        .width(24)        Text(this.taskName)        .fontSize(16)        .decoration({          type: this.isFinished ?                 TextDecorationType.LineThrough :                 TextDecorationType.None        })    }    .onClick(() => {      this.isFinished = !this.isFinished; // 修改状态    })  }}// 父组件:任务列表@Entry@Componentstruct TodoList {  private taskList: string[] = [    '学习鸿蒙开发',    '完成作业',    '运动健身'  ];  build() {    Column() {      ForEach(this.taskList, (name: string) => {        TaskItem({ taskName: name }) // 传递数据给子组件      })    }  }}

5.4 数据流向

六、@Event:⼦组件向⽗组件通信

6.1 什么是@Event?

@Event ⽤于⼦组件向⽗组件输出事件/通知。实现⼦→⽗的单向通信。

6.2 基本语法

// ⼦组件定义@Componentstruct ChildComponent {@Event onDelete: (id: number) => void; // 定义事件build() {Button('删除') .onClick(() => {this.onDelete(1); // 触发事件 }) }}

6.3 示例:删除任务

// 子组件@Componentstruct TaskItem {  @Param taskName: string = '';  @Param taskId: number = 0;  @Event onDelete: (id: number) => void;  build() {    Row({ space: 15 }) {      Text(this.taskName).layoutWeight(1)      Button('删除')        .onClick(() => {          this.onDelete(this.taskId); // 通知父组件删除        })    }  }}// 父组件@Entry@Componentstruct TodoList {  @Local tasks: Task[] = [    new Task(1, '学习鸿蒙'),    new Task(2, '写代码'),    new Task(3, '运动')  ];  deleteTask(id: number) {    this.tasks = this.tasks.filter(t => t.id !== id); // 删除逻辑  }  build() {    Column() {      ForEach(this.tasks, (task: Task) => {        TaskItem({          taskName: task.name,          taskId: task.id,          onDelete: (id) => {            this.deleteTask(id); // 处理删除事件          }        })      })    }  }}class Task {  id: number;  name: string;  constructor(id: number, name: string) {    this.id = id;    this.name = name;  }}

6.4 @Param + @Event 双向通信

学会这两个装饰器,你就可以实现⽗⼦组件的完美通信!

七、@ObservedV2 + @Trace:对象属性观测

7.1 什么是@ObservedV2?

当需要管理对象数据时,普通装饰器可能不够⽤。@ObservedV2 让对象的属性变化可以被追踪。 

7.2 什么是@Trace?

@Trace 精确指定哪些属性需要追踪变化。只追踪被装饰的属性,优化性能。

7.3 基本语法

@ObservedV2class 类名 {  @Trace 属性名:类型 = 初始值; // 追踪这个属性  属性名:类型 = 初始值;        // 不追踪}

7.4 示例:任务对象

// 定义可观测的任务类@ObservedV2class Task {  @Trace name: string = '';        // 追踪:名称变化  @Trace isFinished: boolean = false; // 追踪:状态变化  deadline: string = '';           // 不追踪:不影响UI  constructor(name: string) {    this.name = name;  }}// 使用@Entry@Componentstruct TaskPage {  @Local task: Task = new Task('学习鸿蒙');  build() {    Column() {      Text(this.task.name)               // 变化时自动更新      Text(this.task.isFinished ? '已完成' : '进行中') // 变化时自动更新      Text(this.task.deadline)            // 变化时不会更新      Button('完成任务')        .onClick(() => {          this.task.isFinished = true;    // 触发UI更新        })    }  }}

7.5 ⼯作原理

⼋、Repeat:⾼效列表渲染

8.1 什么是Repeat?

Repeat 是鸿蒙提供的⾼效列表渲染组件,特别适合渲染⼤量数据。

8.2 两种模式

8.3 基本语法

// ⾮懒加载Repeat(数组).each((item) => {// 渲染每个item})// 懒加载Repeat(数组) .lazy(true) .each((item) => {// 渲染 })

8.4 示例:任务列表

@Entry@Componentstruct TaskList {  @Local tasks: string[] = [    '学习鸿蒙开发',    '完成作业',    '运动健身',    '阅读书籍'  ];  build() {    Column({ space: 10 }) {      // 使用 Repeat 渲染      Repeat(this.tasks).each((taskName: string) => {        Row({ space: 15 }) {          Text(taskName)        }        .width('100%')        .padding(16)        .backgroundColor('#FFFFFF')      })    }    .padding(20)  }}
九、AppStorageV2 + PersistenceV2:全局存储

9.1 存储⼯具对⽐

9.2 AppStorageV2:全局共享

import { AppStorageV2 } from '@kit.ArkUI';// 存储数据AppStorageV2.setOrCreate('username', '小明');AppStorageV2.setOrCreate('theme', 'dark');// 读取数据const username = AppStorageV2.get<string>('username');const theme = AppStorageV2.get<string>('theme');// 删除数据AppStorageV2.delete('username');// 检查是否存在const hasKey = AppStorageV2.has('username');

9.3 PersistenceV2:持久化存储

import { PersistenceV2 } from '@kit.ArkUI';// 存储数据(⾃动持久化,APP关闭后不丢失)PersistenceV2.setOrCreate('userToken', 'abc123');PersistenceV2.setOrCreate('userSettings', { theme: 'dark', lang: 'zh' });// 读取数据const token = PersistenceV2.get<string>('userToken');// 删除数据PersistenceV2.delete('userToken');// 清空所有PersistenceV2.clear();

9.4 完整示例:⽤户登录状态

import { PersistenceV2 } from '@kit.ArkUI';// Key定义const KEY_IS_LOGGED_IN = 'isLoggedIn';const KEY_USERNAME = 'username';@Entry@Componentstruct LoginPage {  @Local username: string = '';  @Local isLoggedIn: boolean = false;    aboutToAppear() {    // 读取持久化数据    this.isLoggedIn = PersistenceV2.get<boolean>(KEY_IS_LOGGED_IN) ?? false;    this.username = PersistenceV2.get<string>(KEY_USERNAME) ?? '未登录';  }    login() {    // 登录成功,保存状态    this.isLoggedIn = true;    this.username = '小明';    PersistenceV2.setOrCreate(KEY_IS_LOGGED_IN, true);    PersistenceV2.setOrCreate(KEY_USERNAME, '小明');  }  logout() {    // 退出登录,清除状态    this.isLoggedIn = false;    this.username = '未登录';    PersistenceV2.delete(KEY_IS_LOGGED_IN);    PersistenceV2.delete(KEY_USERNAME);  }  build() {    Column({ space: 20 }) {      if (this.isLoggedIn) {        Text('欢迎,' + this.username + '!')        Button('退出登录')          .onClick(() => this.logout())      } else {        Text('请登录')        Button('登录')          .onClick(() => this.login())      }    }  }}
⼗、实战:完整待办事项应⽤

让我们综合运⽤所有知识,实现⼀个完整的待办事项应⽤!

完整代码

import { PersistenceV2 } from '@kit.ArkUI';// 定义任务类@ObservedV2class Task {  @Trace id: number = 0;  @Trace name: string = '';  @Trace isFinished: boolean = false;  constructor(id: number, name: string) {    this.id = id;    this.name = name;    this.isFinished = false;  }}// 持久化Keyconst KEY_TASKS = 'tasks';// 任务项组件@Componentstruct TaskItem {  @Param task: Task = new Task(0, '');  @Event onToggle: () => void;  @Event onDelete: () => void;  build() {    Row({ space: 15 }) {      Checkbox()        .select(this.task.isFinished)        .onChange(() => this.onToggle())      Text(this.task.name)        .fontSize(16)        .layoutWeight(1)        .decoration({          type: this.task.isFinished ?                TextDecorationType.LineThrough :                TextDecorationType.None        })      Button('删除')        .fontSize(12)        .type(ButtonType.Capsule)        .backgroundColor(Color.Red)        .onClick(() => this.onDelete())    }    .width('100%')    .padding(16)    .backgroundColor('#FFFFFF')    .borderRadius(8)  }}// 主页面@Entry@Componentstruct TodoApp {  @Local tasks: Task[] = [];  aboutToAppear() {    this.loadTasks();  }  loadTasks() {    const saved = PersistenceV2.get<Task[]>(KEY_TASKS);    if (saved) {      this.tasks = saved.map(t => new Task(t.id, t.name));    }  }  saveTasks() {    PersistenceV2.setOrCreate(KEY_TASKS, this.tasks);  }  addTask(name: string) {    this.tasks.push(new Task(this.tasks.length + 1, name));    this.saveTasks();  }  toggleTask(id: number) {    const task = this.tasks.find(t => t.id === id);    if (task) {      task.isFinished = !task.isFinished;      this.saveTasks();    }  }  deleteTask(id: number) {    this.tasks = this.tasks.filter(t => t.id !== id);    this.saveTasks();  }  build() {    Column({ space: 15 }) {      Text('我的待办')        .fontSize(28)        .fontWeight(FontWeight.Bold)      // 渲染任务列表      ForEach(this.tasks, (task: Task) => {        TaskItem({          task: task,          onToggle: () => this.toggleTask(task.id),          onDelete: () => this.deleteTask(task.id)        })      })      // 添加任务      Button('+ 添加任务')        .width('100%')        .onClick(() => {          this.addTask('新任务' + (this.tasks.length + 1));        })    }    .width('100%')    .padding(20)    .backgroundColor('#F5F5F5')  }}

功能特点

✅ 添加任务

✅ 删除任务

✅ 标记完成状态

✅ 数据持久化(关闭APP不丢失)

✅  @ObservedV2 + @Trace 精确追踪

✅  @Param + @Event ⽗⼦通信 

⼗⼀、总结

11.1 知识体系回顾

11.2 选择指南

11.3 学习路径

结语

恭喜你!已经掌握了鸿蒙状态管理V2的核⼼知识!

状态管理是鸿蒙开发的基础,也是进阶的必经之路。掌握这些知识点后,你就可以轻松实现各种交 互逻辑,开发出流畅的APP了。 如果觉得⽂章对你有帮助,欢迎点赞收藏!

有问题也可以在评论区留⾔讨论~

本文作者:誉天HarmonyOS资深讲师——王琦老师

关注我

持续获取更多

鸿蒙开发⼲货!

最新文章

随机文章