及时做APP开发实战(一)-MVVM架构设计实践
2026/7/14 2:06:32 网站建设 项目流程

及时做APP开发实战(一)-MVVM架构设计实践

本文将详细介绍如何在HarmonyOS NEXT应用中实现MVVM架构,以"及时做"番茄待办应用为例,展示分层设计的最佳实践。

一、为什么选择MVVM架构?

在移动应用开发中,良好的架构设计是项目可维护性和扩展性的基石。MVVM(Model-View-ViewModel)模式通过清晰的职责分离,让代码更易于理解和维护。

1.1 传统开发模式的痛点

很多初学者习惯将所有代码写在页面组件中,导致:

  • 代码臃肿:一个文件动辄上千行
  • 难以测试:业务逻辑与UI耦合
  • 复用困难:相同逻辑重复编写
  • 维护成本高:修改一处影响多处

1.2 MVVM的优势

MVVM模式通过三层分离解决了上述问题:

┌─────────────────────────────────────┐ │ View(视图层) │ │ 负责UI展示和用户交互 │ └──────────────┬──────────────────────┘ │ 数据绑定 ┌──────────────▼──────────────────────┐ │ ViewModel(业务逻辑层) │ │ 负责业务处理和状态管理 │ └──────────────┬──────────────────────┘ │ 数据操作 ┌──────────────▼──────────────────────┐ │ Model(数据模型层) │ │ 负责数据定义和存储 │ └─────────────────────────────────────┘

【图1:MVVM架构层次示意图】

二、项目结构设计

在"及时做"应用中,我们采用以下目录结构:

entry/src/main/ets/ ├── model/ # 数据模型层 │ ├── TodoItem.ets # 待办任务模型 │ └── PomodoroRecord.ets # 番茄钟记录模型 ├── viewmodel/ # 业务逻辑层 │ ├── TodoViewModel.ets # 待办业务管理 │ └── PomodoroViewModel.ets # 番茄钟业务管理 ├── utils/ # 工具类层 │ ├── PreferencesHelper.ets # 持久化服务 │ └── CommonUtil.ets # 通用工具 └── pages/ # UI页面层 └── Index.ets # 主页面

这种结构清晰明了,每层职责分明:

  • model:定义数据结构,不包含业务逻辑
  • viewmodel:处理业务逻辑,协调model和view
  • utils:提供通用功能,如存储、格式化等
  • pages:负责UI渲染和用户交互

【图2:项目目录结构截图】

三、Model层设计

Model层是数据的基础,我们使用ArkTS的interface定义数据结构。

3.1 待办任务模型

/** * 待办任务数据模型 */exportinterfaceTodoItem{/** 唯一标识,使用时间戳生成 */id:number;/** 任务文本内容 */text:string;/** 完成状态 */completed:boolean;/** 创建时间戳 */createdAt:number;/** 番茄钟完成次数 */pomodoroCount:number;}/** * 创建新的待办任务 */exportfunctioncreateTodoItem(text:string):TodoItem{return{id:Date.now(),text:text,completed:false,createdAt:Date.now(),pomodoroCount:0};}

设计要点:

  1. 使用interface而非class:ArkTS推荐使用interface定义纯数据结构
  2. 语义化命名:每个字段都有清晰的注释说明
  3. 工厂函数:提供createTodoItem简化对象创建
  4. 时间戳ID:使用Date.now()生成唯一标识

3.2 番茄钟记录模型

/** * 番茄钟记录数据模型 */exportinterfacePomodoroRecord{/** 唯一标识 */id:number;/** 关联的待办任务ID */todoId:number;/** 单次专注时长(分钟) */duration:number;/** 完成时间戳 */completedAt:number;}/** * 创建新的番茄钟记录 */exportfunctioncreatePomodoroRecord(todoId:number,duration:number):PomodoroRecord{return{id:Date.now(),todoId:todoId,duration:duration,completedAt:Date.now()};}

注意todoId字段的设计,它建立了番茄钟记录与待办任务的关联关系,这是关系型数据建模的关键。

四、ViewModel层实现

ViewModel是MVVM的核心,它承上启下,既管理数据又为View提供服务。

4.1 待办业务管理

import{TodoItem,createTodoItem}from'../model/TodoItem';import{PreferencesHelper}from'../utils/PreferencesHelper';/** * 待办任务业务逻辑管理类 */exportclassTodoViewModel{privatepreferencesHelper:PreferencesHelper|null=null;privatetodoList:TodoItem[]=[];/** * 初始化ViewModel */asyncinit():Promise<void>{this.preferencesHelper=awaitPreferencesHelper.getInstance();awaitthis.loadTodoList();}/** * 加载待办列表 */privateasyncloadTodoList():Promise<void>{if(this.preferencesHelper){this.todoList=awaitthis.preferencesHelper.getTodoList();}}/** * 添加新待办 */asyncaddTodo(text:string):Promise<TodoItem>{consttodo=createTodoItem(text);this.todoList.push(todo);if(this.preferencesHelper){awaitthis.preferencesHelper.addTodo(todo);}returntodo;}/** * 切换待办完成状态 */asynctoggleTodoComplete(todoId:number):Promise<void>{consttodo=this.todoList.find(item=>item.id===todoId);if(todo){todo.completed=!todo.completed;awaitthis.updateTodo(todo);}}/** * 获取未完成的待办数量 */getActiveTodoCount():number{returnthis.todoList.filter(item=>!item.completed).length;}}

【图3:主页图】

4.2 设计要点解析

  1. 异步初始化:init方法使用async/await处理异步加载
  2. 内存缓存:todoList保持内存中的数据,减少IO操作
  3. 单一职责:每个方法只做一件事
  4. 错误处理:通过null检查避免空指针异常

4.3 番茄钟业务管理

exportclassPomodoroViewModel{privatepreferencesHelper:PreferencesHelper|null=null;privatetodoViewModel:TodoViewModel|null=null;privaterecords:PomodoroRecord[]=[];// 番茄钟配置privatestaticreadonlyDEFAULT_DURATION=25;privatestaticreadonlySHORT_BREAK=5;privatestaticreadonlyLONG_BREAK=15;/** * 完成一次番茄钟 */asynccompletePomodoro(todoId:number,duration:number=PomodoroViewModel.DEFAULT_DURATION):Promise<PomodoroRecord>{constrecord=createPomodoroRecord(todoId,duration);this.records.push(record);if(this.preferencesHelper){awaitthis.preferencesHelper.addPomodoroRecord(record);}// 更新待办的番茄钟完成次数if(this.todoViewModel){awaitthis.todoViewModel.incrementPomodoroCount(todoId);}returnrecord;}/** * 获取今日专注总时长 */getTodayTotalDuration():number{consttoday=newDate();today.setHours(0,0,0,0);consttodayTimestamp=today.getTime();returnthis.records.filter(record=>record.completedAt>=todayTimestamp).reduce((total,record)=>total+record.duration,0);}}

这里体现了ViewModel之间的协作:PomodoroViewModel需要通知TodoViewModel更新番茄钟计数。

五、View层使用示例

在页面组件中,我们通过ViewModel获取和操作数据:

import{TodoViewModel}from'../viewmodel/TodoViewModel';@Entry@Componentstruct Index{@StatetodoList:TodoItem[]=[];privatetodoViewModel:TodoViewModel=newTodoViewModel();asyncaboutToAppear(){awaitthis.todoViewModel.init();this.todoList=this.todoViewModel.getTodoList();}build(){Column(){// UI渲染ForEach(this.todoList,(todo:TodoItem)=>{Text(todo.text).onClick(async()=>{awaitthis.todoViewModel.toggleTodoComplete(todo.id);this.todoList=this.todoViewModel.getTodoList();})})}}}

关键点:

  1. 生命周期初始化:在aboutToAppear中初始化ViewModel
  2. 状态管理:使用@State装饰器实现响应式更新
  3. 数据绑定:UI直接绑定ViewModel的数据

六、架构优势总结

通过MVVM架构,我们实现了:

  1. 代码组织清晰:每层职责明确,易于定位代码
  2. 可测试性强:ViewModel可以独立测试,不依赖UI
  3. 复用性好:ViewModel可在多个页面复用
  4. 维护成本低:修改业务逻辑不影响UI结构

在HarmonyOS NEXT开发中,MVVM模式与ArkUI的响应式特性完美契合,是构建高质量应用的理想选择。

七、最佳实践建议

  1. 保持Model纯粹:只定义数据结构,不包含业务逻辑
  2. ViewModel单一职责:一个ViewModel管理一类业务
  3. 合理使用工具类:通用功能抽取到utils层
  4. 异步处理规范:统一使用async/await处理异步操作
  5. 错误处理完善:关键操作添加try-catch和null检查

通过这套架构,"及时做"应用具备了良好的可扩展性,为后续功能开发打下了坚实基础。


需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询