鸿蒙状态管理V2实战:从零构建MVVM架构的应用

兄弟们,今天咱们来聊聊鸿蒙开发中的状态管理V2和MVVM架构,通过一个完整的TodoList应用,手把手带大家掌握这个强大的开发模式!

什么是MVVM模式?

在应用开发中,UI的更新需要随着数据状态的变化进行实时同步,这种同步直接影响应用性能和用户体验。为了解决数据与UI同步的复杂性,ArkUI采用了Model-View-ViewModel(MVVM)架构模式。

简单来说:

  • Model:存储和管理应用数据及业务逻辑,不直接与用户界面交互
  • View:负责用户界面展示数据并与用户交互,不包含业务逻辑
  • ViewModel:作为连接Model和View的桥梁,管理UI状态和交互逻辑

状态管理V2装饰器全家福

在开始实战前,先了解下状态管理V2提供的核心装饰器:

  • @Local:管理组件内部状态
  • @Param:实现组件接受外部输入
  • @Event:实现组件对外输出
  • @ObservedV2 + @Trace:实现类属性深度观测
  • @Monitor:监听状态变量变化
  • @Computed:定义计算属性
  • @Builder:实现自定义构建函数

常规实战开始:一步步构建TodoList

第一步:基础静态列表

typescript 复制代码
@Entry
@ComponentV2
struct TodoList {
  build() {
    Column() {
      Text('待办')
        .fontSize(40)
        .margin({ bottom: 10 })
      Text('Task1')
      Text('Task2')
      Text('Task3')
    }
  }
}

这是最基础的版本,任务都是写死的静态数据。

第二步:添加@Local实现状态管理

typescript 复制代码
@Entry
@ComponentV2
struct TodoList {
  @Local isFinish: boolean = false;

  build() {
    Column() {
      Text('待办')
        .fontSize(40)
        .margin({ bottom: 10 })
      Row() {
        Image(this.isFinish ? $r('app.media.finished') : $r('app.media.unfinished'))
          .width(28)
          .height(28)
        Text('Task1')
          .decoration({ type: this.isFinish ? TextDecorationType.LineThrough : TextDecorationType.None })
      }
      .onClick(() => this.isFinish = !this.isFinish)
    }
  }
}

这里使用@Local装饰器管理任务完成状态,点击任务时可以切换完成状态。

第三步:@Param实现组件传参

typescript 复制代码
@ComponentV2
struct TaskItem {
  @Param taskName: string = '';
  @Param @Once isFinish: boolean = false;

  build() {
    Row() {
      Image(this.isFinish ? $r('app.media.finished') : $r('app.media.unfinished'))
        .width(28)
        .height(28)
      Text(this.taskName)
        .decoration({ type: this.isFinish ? TextDecorationType.LineThrough : TextDecorationType.None })
    }
    .onClick(() => this.isFinish = !this.isFinish)
  }
}

通过@Param实现父组件向子组件传递数据,@Once允许在子组件内更新传入的值。

第四步:@Event实现子组件事件传递

typescript 复制代码
@ComponentV2
struct TaskItem {
  @Param taskName: string = '';
  @Param @Once isFinish: boolean = false;
  @Event deleteTask: () => void = () => {};

  build() {
    Row() {
      Image(this.isFinish ? $r('app.media.finished') : $r('app.media.unfinished'))
        .width(28)
        .height(28)
      Text(this.taskName)
        .decoration({ type: this.isFinish ? TextDecorationType.LineThrough : TextDecorationType.None })
      Button('删除')
        .onClick(() => this.deleteTask())
    }
    .onClick(() => this.isFinish = !this.isFinish)
  }
}

@Event装饰器让子组件可以向父组件传递事件,实现真正的双向数据流。

第五步:Repeat优化列表渲染

typescript 复制代码
Repeat<string>(this.tasks)
  .each((obj: RepeatItem<string>) => {
    TaskItem({
      taskName: obj.item,
      isFinish: false,
      deleteTask: () => this.tasks.splice(this.tasks.indexOf(obj.item), 1)
    })
  })

Repeat提供了高效的列表渲染,支持懒加载和非懒加载两种模式,大幅提升性能。

第六步:@ObservedV2和@Trace深度观测

typescript 复制代码
@ObservedV2
class Task {
  taskName: string = '';
  @Trace isFinish: boolean = false;

  constructor (taskName: string, isFinish: boolean) {
    this.taskName = taskName;
    this.isFinish = isFinish;
  }
}

@ObservedV2@Trace组合使用,可以深度观测嵌套对象的属性变化,解决了复杂数据结构的响应式问题。

第七步:@Monitor和@Computed监听与计算

typescript 复制代码
@Monitor('task.isFinish')
onTaskFinished(mon: IMonitor) {
  console.log('任务' + this.task.taskName + '的完成状态从' + mon.value()?.before + '变为了' + mon.value()?.now);
}

@Computed
get tasksUnfinished(): number {
  return this.tasks.filter(task => !task.isFinish).length;
}

@Monitor监听状态变化,@Computed自动计算衍生数据,两者结合让状态管理更加智能。

第八步:AppStorageV2全局状态管理

typescript 复制代码
@Local setting: Setting = AppStorageV2.connect(Setting, 'Setting', () => new Setting())!;

AppStorageV2实现了跨Ability、跨页面的全局状态共享,非常适合应用级别的设置管理。

第九步:PersistenceV2数据持久化

typescript 复制代码
@Local taskList: TaskList = PersistenceV2.connect(TaskList, 'TaskList', () => new TaskList([]))!;

PersistenceV2将数据持久化到设备磁盘,应用重启后数据依然保持,提供了完整的持久化解决方案。

第十步:@Builder组件复用

typescript 复制代码
@Builder function ActionButton(text: string, onClick:() => void) {
  Button(text, { buttonStyle: ButtonStyleMode.NORMAL })
    .onClick(onClick)
    .margin({ left: 10, right: 10, top: 5, bottom: 5 })
}

@Builder装饰器让UI组件可以像函数一样复用,大大提升代码的可维护性。

MVVM架构重构

当应用变得复杂时,我们需要用MVVM模式重构代码,实现真正的关注点分离。

Model层:纯数据逻辑

TaskModel.ets

typescript 复制代码
export default class TaskModel {
  taskName: string = 'Todo';
  isFinish: boolean = false;
}

TaskListModel.ets

typescript 复制代码
export default class TaskListModel {
  tasks: TaskModel[] = [];

  async loadTasks(context: common.UIAbilityContext){
    // 从本地文件加载任务数据
  }
}

Model层只关心数据,不涉及任何UI逻辑。

ViewModel层:业务逻辑处理

TaskViewModel.ets

typescript 复制代码
@ObservedV2
export default class TaskViewModel {
  @Trace taskName: string = 'Todo';
  @Trace isFinish: boolean = false;

  updateIsFinish(): void {
    this.isFinish = !this.isFinish;
  }
}

TaskListViewModel.ets

typescript 复制代码
@ObservedV2
export default class TaskListViewModel {
  @Type(TaskViewModel)
  @Trace tasks: TaskViewModel[] = [];

  finishAll(ifFinish: boolean): void {
    for(let task of this.tasks){
      task.isFinish = ifFinish;
    }
  }
}

ViewModel处理所有业务逻辑,为View层提供准备好的数据。

View层:纯UI展示

ListView.ets

typescript 复制代码
@ComponentV2
export default struct ListView {
  @Param taskList: TaskListViewModel = new TaskListViewModel();
  @Param setting: Setting = new Setting();

  build() {
    Repeat<TaskViewModel>(this.taskList.tasks.filter(task => this.setting.showCompletedTask || !task.isFinish))
      .each((obj: RepeatItem<TaskViewModel>) => {
        TaskItem({
          task: obj.item,
          deleteTask: () => this.taskList.removeTask(obj.item)
        }).margin(5)
      })
  }
}

View层只负责UI渲染和用户交互,所有数据都通过ViewModel获取。

核心优势总结

通过这个完整的TodoList示例,我们可以看到鸿蒙状态管理V2结合MVVM架构的几大优势:

  1. 清晰的职责分离:Model、View、ViewModel各司其职
  2. 强大的响应式系统:数据变化自动触发UI更新
  3. 优秀的性能表现:Repeat、Computed等特性优化渲染
  4. 完善的持久化方案:PersistenceV2提供开箱即用的数据持久化
  5. 灵活的组件通信:Param、Event实现父子组件高效通信
  6. 便捷的全局状态:AppStorageV2轻松管理应用级状态

操作建议

兄弟们在实际项目中应用时,需要注意以下几点:

  1. 合理使用装饰器:根据场景选择合适的装饰器组合
  2. 性能监控:注意Monitor回调中的性能消耗
  3. 测试驱动:ViewModel的纯函数特性非常适合单元测试

MVVM模式配合状态管理V2,确实能够大幅提升鸿蒙应用的开发效率和代码质量。

希望这个TodoList示例能帮助兄弟们更好地理解和应用这一强大架构,开发出代码质量上乘的鸿蒙应用!

相关推荐
梦想CAD控件4 分钟前
在线CAD开发包结构与功能说明
前端·javascript·vue.js
张拭心9 分钟前
春节后,有些公司明确要求 AI 经验了
android·前端·人工智能
时光不负努力10 分钟前
typescript常用的dom 元素类型
前端·typescript
小怪点点15 分钟前
大文件切片上传
前端
时光不负努力16 分钟前
TS 常用工具类型
前端·javascript·typescript
SuperEugene17 分钟前
Vue状态管理扫盲篇:Vuex 到 Pinia | 为什么大家都在迁移?核心用法对比
前端·vue.js·面试
张拭心19 分钟前
Android 17 来了!新特性介绍与适配建议
android·前端
徐小夕24 分钟前
pxcharts-vue:一款专为 Vue3 打造的开源多维表格解决方案
前端·vue.js·github
Hilaku24 分钟前
我会如何考核一个在简历里大谈 AI 提效的高级前端?
前端·javascript·面试
青青家的小灰灰1 小时前
React 反模式(Anti-Patterns)排查手册:从性能杀手到逻辑陷阱
前端·javascript·react.js