MVVM 架构核心概念与分层设计

鸿蒙 ArkUI 的 MVVM 架构 (Model-View-ViewModel)通过 声明式编程 和 响应式状态管理 实现 UI 与数据的高效同步,其核心在于 数据驱动 UI 更新 。

三层架构职责划分
  1. Model 层

    • 负责数据定义、业务逻辑与数据持久化(如数据库、网络请求)。
    • 示例:TodoListModel 管理待办事项的增删改查。
    • 特点 :纯数据模型,不包含 UI 逻辑。
  2. ViewModel 层

    • 作为 Model 与 View 的桥梁,处理数据转换、业务逻辑和状态管理。
    • 通过 @State@Link 等装饰器实现与 View 的绑定。
    • 特点 :无 UI 代码,专注逻辑处理。
  3. View 层

    • 负责 UI 布局与用户交互,通过绑定 ViewModel 数据实现动态更新。
    • 特点 :无业务逻辑,仅包含声明式 UI 代码。

数据流转与通信规范
  1. 单向数据流推荐

    • 父 → 子 :使用 @Prop 传递数据(单向绑定)。
    • 子 → 父 :通过事件回调(如 $emit)通知父组件更新。
    • 跨组件通信 :推荐使用 全局事件总线 或 共享 ViewModel 。
  2. 装饰器体系

    • @State:组件内局部状态,驱动 UI 更新。
    • @Prop:父组件向子组件传递数据(单向,深拷贝)。
    • @Link:父子组件双向绑定(谨慎使用,避免复杂依赖)。
    • @Observed:标记 Model 类,使其具备响应式能力。

备忘录应用实战(标准 ArkTS 实现)
1. 目录结构
src/
├── ets/
│   ├── model/           # 数据模型(@Observed 类)
│   ├── viewmodel/       # 视图模型(@State + 业务逻辑)
│   ├── view/            # UI 组件(@Component)
│   └── pages/          # 页面入口(@Entry)
2. 代码示例
// model/ThingsModel.ets
@Observed
export class ThingsModel {
  @Track thingsName: string;
  @Track isFinish: boolean;

  // 添加构造函数解决初始化报错
  constructor(thingsName: string, isFinish: boolean) {
    this.thingsName = thingsName;
    this.isFinish = isFinish;
  }
}

// viewmodel/ThingsViewModel.ets
export class ThingsViewModel {
  @Track tasks: ThingsModel[] = []; // 添加@Track装饰器实现响应式更新

  loadTasks() {
    this.tasks = [
      new ThingsModel('学习高数', false),
      new ThingsModel('阅读文档', true)
    ];
  }

  // 添加任务状态切换方法
  toggleFinish(index: number) {
    if (index >= 0 && index < this.tasks.length) {
      this.tasks[index].isFinish = !this.tasks[index].isFinish;
    }
  }
}

// view/ThingsComponent.ets
@Component
export struct ThingsComponent {
  @Prop task: ThingsModel;
  private index: number = -1; // 接收父组件传递的索引
  @Link selectedIndex: number;

  // 添加索引参数解决index未定义问题
  build() {
    Row() {
      Image(this.task.isFinish ? $r('app.media.finished') : $r('app.media.unfinished'))
        .width(28)
        .height(28)
        .onClick(() => {
          // 通过事件回调更新状态
          this.selectedIndex = this.index;
          // 调用ViewModel方法更新任务状态
          getViewModel().toggleFinish(this.index);
        })
      Text(this.task.thingsName)
        .fontSize(24)
        .decoration({
          type: this.task.isFinish ? TextDecorationType.LineThrough : TextDecorationType.None
        })
    }
    .padding(10)
  }
}

// 全局ViewModel单例(解决状态共享问题)
let globalViewModel: ThingsViewModel | null = null;

export function getViewModel(): ThingsViewModel {
  if (!globalViewModel) {
    globalViewModel = new ThingsViewModel();
    globalViewModel.loadTasks();
  }
  return globalViewModel;
}

// pages/Index.ets
@Entry
@Component
struct Index {
  @State selectedIndex: number = -1;
  private viewModel: ThingsViewModel = getViewModel();

  build() {
    Column() {
      // 使用ForEach替代LazyForEach(小数据量场景)
      ForEach(this.viewModel.tasks, (item: ThingsModel, index: number) => {
        ThingsComponent({
          task: item,
          index: index, // 传递当前索引到子组件
          selectedIndex: $selectedIndex // 双向绑定语法
        })
      }, (item: ThingsModel) => item.thingsName)
    }
    .width('100%')
    .padding(20)
  }
}
3. 优化点说明
  • LazyForEach :仅渲染可见区域列表项,提升长列表性能。
  • 事件替代 @Link :通过事件回调更新父组件状态,减少双向绑定的复杂性。
  • @Observed + @Track :实现 Model 层数据的响应式更新。

最佳实践与性能优化
  1. 状态管理

    • 优先使用 @Prop + 事件 :避免 @Link 的双向绑定开销。
    • 全局状态共享 :通过单例 ViewModel 或全局事件总线管理跨页面状态。
  2. 性能优化

    • 懒加载与分页 :ViewModel 中按需加载数据(如分页请求)。
    • 组件复用 :使用 @Builder 方法复用 UI 片段,减少重复构建。
    • 长列表优化 :LazyForEach + RecycleList 实现高效滚动列表。
  3. 大型项目架构

    • 模块化设计 :按功能划分模块,每个模块包含独立的 Model/ViewModel/View。
    • 服务层抽象 :将网络请求、数据库操作封装为独立服务类。
    • 事件总线 :使用 EventBus 处理跨模块通信,避免直接依赖。

总结:MVVM 架构的核心价值
  • 解耦与可维护性 :各层职责明确,修改逻辑或 UI 时不会相互影响。
  • 高效的状态管理 :通过装饰器体系实现数据与 UI 的自动同步,减少手动更新代码。
  • 组件化开发 :支持组件复用与拆分,提升开发效率。
  • 多端一致性 :一套架构适配多种设备,确保用户体验一致。

通过遵循 MVVM 的设计原则和最佳实践,开发者能够构建出结构清晰、高性能的鸿蒙应用,实现高效的全场景开发。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐