HarmonyOS 鸿蒙Next中MVVM模式

HarmonyOS 鸿蒙Next中MVVM模式 HarmonyOS有无MVVM模式的开发介绍文档,以及示例

8 回复

1、楼主,使用MVVM模式架构需要先了解ArkUI中的 状态管理 相关知识。状态管理目前分为两个版本V1和V2。

状态管理(V1)

状态管理(V2)

2、然后在进去MVVM相关架构的学习。

MVVM模式V1

MVVM模式V2

更多关于HarmonyOS 鸿蒙Next中MVVM模式的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


1.为了更好地组织代码和提升可维护性,使用MVVM模式重构代码,进一步将数据层(Model)、逻辑层(ViewModel)和展示层(View)分离。

MVVM参考文档:MVVM模式(状态管理V2)-状态管理(V2)-学习UI范式状态管理-UI开发 (ArkTS声明式开发范式)-ArkUI(方舟UI框架)-应用框架 - 华为HarmonyOS开发者

2.楼主想要学习MVVM架构的话最好是结合V2的状态变量:
V2所属装饰器-状态管理(V2)-学习UI范式状态管理-UI开发 (ArkTS声明式开发范式)-ArkUI(方舟UI框架)-应用框架 - 华为HarmonyOS开发者

参考官文:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-mvvm

效果图如下:

https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/085/834/069/0260086000085834069.20250910160726.96351421057070851451867232202028:50001231000000:2800:516CC0BF82E5BBDAC705906FCE7A702654F564825FD4C9C2DAE53D8764EF6A72.gif

Index.ets

import { common } from '@kit.AbilityKit';

// import ViewModel

import TodoListViewModel from '../ViewModel/TodoListViewModel';

// import View

import { TodoComponent } from '../View/TodoComponent';

import { AllChooseComponent } from '../View/AllChooseComponent';

import { TodoListComponent } from '../View/TodoListComponent';

@Entry

@Component

struct TodoList {

  @State todoListViewModel: TodoListViewModel = new TodoListViewModel(); // View绑定ViewModel的数据

  private context = this.getUIContext().getHostContext() as common.UIAbilityContext;

  async aboutToAppear() {

    await this.todoListViewModel.loadTasks(this.context);

  }

  build() {

    Column() {

      Row({ space: 40 }) {

        // 全部待办

        TodoComponent()

        // 全选

        AllChooseComponent({ todoListViewModel: this.todoListViewModel })

      }

      Column() {

        TodoListComponent({ thingsViewModelArray: this.todoListViewModel.things })

      }

    }

    .height('100%')

    .width('100%')

    .margin({ top: 5, bottom: 5 })

    .backgroundColor('#90f1f3f5')

  }

}

ThingModel.ets

export default class ThingModel {

  thingsName: string = 'Todo';

  isFinish: boolean = false;

}

TodoListModel.ets

import { common } from '@kit.AbilityKit';

import { util } from '@kit.ArkTs';

import ThingModel from './ThingModel';

export default class TodoListModel {

  things: Array<ThingModel> = [];

  constructor(things: Array<ThingModel>) {

    this.things = things;

  }

  async loadTasks(context: common.UIAbilityContext) {

    let getJson = await context.resourceManager.getRawFileContent('default_tasks.json');

    let textDecoderOptions: util.TextDecoderOptions = { ignoreBOM: true };

    let textDecoder = util.TextDecoder.create('utf-8', textDecoderOptions);

    let result = textDecoder.decodeToString(getJson, { stream: false });

    this.things = JSON.parse(result);

  }

}

AllChooseComponent.ets

import TodoListViewModel from "../ViewModel/TodoListViewModel";

@Component

export struct AllChooseComponent {

  @State titleName: string = '全选';

  @Link todoListViewModel: TodoListViewModel;

  build() {

    Row() {

      Button(`${this.titleName}`, { type: ButtonType.Capsule })

        .onClick(() => {

          this.todoListViewModel.chooseAll(); // View层点击事件发生时,调用ViewModel层方法chooseAll处理逻辑

          this.titleName = this.todoListViewModel.isChoosen ? '全选' : '取消全选';

        })

        .fontSize(30)

        .fontWeight(FontWeight.Bold)

        .backgroundColor('#f7f6cc74')

    }

    .padding({ left: this.todoListViewModel.isChoosen ? 15 : 0 })

    .width('100%')

    .margin({ top: 10, bottom: 10 })

  }

}

ThingsComponent.ets

import ThingsViewModel from "../ViewModel/ThingsViewModel";

@Component

export struct ThingsComponent {

  @Prop things: ThingsViewModel;

  @Builder

  displayIcon(icon: Resource) {

    Image(icon)

      .width(28)

      .height(28)

      .onClick(() => {

        this.things.updateIsFinish(); // View层点击事件发生时,调用ViewModel层方法updateIsFinish处理逻辑

      })

  }

  build() {

    // 待办事项

    Row({ space: 15 }) {

      if(this.things.isFinish) {

        // 此处'app.media.finished'仅作示例,请开发者自行替换,否则imageSource创建失败会导致后续无法正常执行。

        this.displayIcon($r('app.media.finished'));

      } else {

        // 此处'app.media.unfinished'仅作示例,请开发者自行替换,否则imageSource创建失败会导致后续无法正常执行。

        this.displayIcon($r('app.media.unfinished'));

      }

      Text(`${this.things.thingsName}`)

        .fontSize(24)

        .decoration({ type: this.things.isFinish ? TextDecorationType.LineThrough: TextDecorationType.None })

        .onClick(() => {

          this.things.addSuffixes(); // View层点击事件发生时,调用ViewModel层方法addSuffixes处理逻辑

        })

    }

    .height('8%')

    .width('90%')

    .padding({ left: 15 })

    .opacity(this.things.isFinish ? 0.3 : 1)

    .border({ width: 1 })

    .borderColor(Color.White)

    .borderRadius(25)

    .backgroundColor(Color.White)

  }

}

TodoComponent.ets

@Component

export struct TodoComponent {

  build() {

    Row() {

      Text('全部待办')

        .fontSize(30)

        .fontWeight(FontWeight.Bold)

    }

    .padding({ left: 15 })

    .width('50%')

    .margin({ top: 10, bottom: 10 })

  }

}

TodoListComponent.ets

import ThingsViewModel from "../ViewModel/ThingsViewModel";

import { ThingsViewModelArray } from "../ViewModel/TodoListViewModel"

import { ThingsComponent } from "./ThingsComponent";

@Component

export struct TodoListComponent {

  @ObjectLink thingsViewModelArray: ThingsViewModelArray;

  build() {

    Column() {

      List() {

        ForEach(this.thingsViewModelArray, (item: ThingsViewModel) => {

          // 待办事项

          ListItem() {

            ThingsComponent({ things: item })

              .margin(5)

          }

        }, (item: ThingsViewModel) => {

          return item.thingsName;

        })

      }

    }

  }

}

ThingsViewModel.ets

import ThingModel from "../Model/ThingModel";

@Observed

export default class ThingsViewModel {

  @Track thingsName: string = 'Todo';

  @Track isFinish: boolean = false;

  updateTask(things: ThingModel) {

    this.thingsName = things.thingsName;

    this.isFinish = things.isFinish;

  }

  updateIsFinish(): void {

    this.isFinish = !this.isFinish;

  }

  addSuffixes(): void {

    this.thingsName += '啦';

  }

}

TodoListViewModel.ets

import ThingsViewModel from "./ThingsViewModel";

import { common } from "@kit.AbilityKit";

import TodoListModel from "../Model/TodoListModel";

@Observed

export class ThingsViewModelArray extends Array<ThingsViewModel> {

}

@Observed

export default class TodoListViewModel {

  @Track isChoosen: boolean = true;

  @Track things: ThingsViewModelArray = new ThingsViewModelArray();

  async loadTasks(context: common.UIAbilityContext) {

    let todoList = new TodoListModel([]);

    await todoList.loadTasks(context);

    for(let things of todoList.things) {

      let todoListViewModel = new ThingsViewModel();

      todoListViewModel.updateTask(things);

      this.things.push(todoListViewModel);

    }

  }

  chooseAll(): void {

    for(let things of this.things) {

      things.isFinish = this.isChoosen;

    }

    this.isChoosen = !this.isChoosen;

  }

}

default_tasks.json

[

  {"thingsName": "7.30起床", "isFinish": false},

  {"thingsName": "8.30早餐", "isFinish": false},

  {"thingsName": "11.30中餐", "isFinish": false},

  {"thingsName": "17.30晚餐", "isFinish": false},

  {"thingsName": "21.30夜宵", "isFinish": false},

  {"thingsName": "22.30洗澡", "isFinish": false},

  {"thingsName": "1.30睡觉", "isFinish": false}

]

状态管理V1:MVVM模式

状态管理V2:MVVM模式(状态管理V2)

鸿蒙Next中MVVM模式采用ArkTS语言实现,通过声明式UI框架构建数据驱动视图。Model层管理数据与业务逻辑,View层通过自定义组件描述界面结构,ViewModel层使用@State@Prop等装饰器实现数据双向绑定。MVVM架构实现了数据与UI的自动同步,提升开发效率与可维护性。

目前HarmonyOS Next官方文档中提供了基于ArkTS的声明式开发范式,支持MVVM模式开发。您可以在华为开发者官网的“文档”部分查看详细的开发指南和示例代码,其中包含了数据绑定、状态管理和组件化开发的相关内容。建议参考“ArkUI开发框架”文档,其中通过实际案例展示了如何实现数据与UI的分离及响应式更新。

回到顶部