HarmonyOS鸿蒙Next中MVVM模式(状态管理V2实现)

概述

在应用开发中,UI的更新需要随着数据状态的变化进行实时同步,而这种同步往往决定了应用程序的性能和用户体验。为了解决数据与UI同步的复杂性,ArkUI采用了Model-View-ViewModel(MVVM)架构模式。MVVM将应用分为Model、View和ViewModel三个核心部分,实现数据、视图与逻辑的分离。通过这种模式,UI可以随着状态的变化自动更新,无需手动处理,从而更加高效地管理数据和视图的绑定与更新。

Model:负责存储和管理应用的数据以及业务逻辑,不直接与用户界面交互。通常从后端接口获取数据,是应用程序的数据基础,确保数据的一致性和完整性。

View:负责用户界面展示数据并与用户交互,不包含任何业务逻辑。它通过绑定ViewModel层提供的数据来动态更新UI。

ViewModel:负责管理UI状态和交互逻辑。作为连接Model和View的桥梁,ViewModel监控Model数据的变化,通知View更新UI,同时处理用户交互事件并转换为数据操作。

示例

目录结构

--src/main/ets/pages/Index.ets:主页面
--src/main/ets/view/AddView.ets:新增任务组件
--src/main/ets/view/TitleView.ets:标题组件
--src/main/ets/view/ListView.ets:任务列表组件
--src/main/ets/model/TaskModel.ets:页面设计的数据结构
--src/main/ets/vm/TaskViewModel.ets:项目的交互逻辑组件

添加组件代码:

添加组件中的新增事件由父页面传入,新增的方法定义在TaskViewModel中,代码如下

import { TitleView } from '../view/TitleView';
import ListView from '../view/ListView';
import { TaskViewModel } from '../vm/TaskViewModel';
import { promptAction } from '@kit.ArkUI';
import { AddView } from '../view/AddView';

@Entry
@ComponentV2
struct Index {
  @Local
  taskVM: TaskViewModel = new TaskViewModel()

  aboutToAppear(): void {
    this.taskVM.queryTaskList()
    promptAction.showToast({ message: this.taskVM.tasksList[1].taskName })
  }

  build() {
    Column() {
      TitleView({tasksUnfinished:this.taskVM.finishedCount})
      AddView({
        addTask:(taskName)=>{
          this.taskVM.addTask(taskName)
        }
      })
      ListView({
        taskList: this.taskVM.tasksList,
        delTask: (id) => {
          this.taskVM.delTask(id)
        },
        changeFinished: (id, bool) => {
          this.taskVM.updateTaskFinished(id, bool)
        }
      })
    }
  }
}

–src/main/ets/view/AddView.ets:新增任务组件

@ComponentV2
export struct AddView {
  @Local
  name: string = ''
  @Event
  addTask: (taskName: string) => void

  build() {
    Row() {
      TextInput({ placeholder: '请输入任务名', text: $$this.name })
        .layoutWeight(1)
      Button('新增')
        .onClick(() => {
          this.addTask(this.name)
        })
    }
  }
}

–src/main/ets/view/TitleView.ets:标题组件

@ComponentV2
export  struct TitleView {
  @Require
  @Param tasksUnfinished:number

  build() {
    Column() {
      Text('待办')
        .fontSize(40)
        .margin(10)
      Text(`未完成任务:${this.tasksUnfinished}`)
        .margin({ left: 10, bottom: 10 })
    }
  }
}

–src/main/ets/view/ListView.ets:任务列表组件

@ComponentV2
export default struct ListView {
  @Require
  @Param
  taskList: TaskModel[]
  //改变任务状态
  @Event
  changeFinished: (id:number,value: boolean) => void
  @Event
  delTask: (id: number) => void

  build() {
    Column() {
      Row() {
        Text('任务名')
          .textAlign(TextAlign.Center)
          .fontSize(18)
          .layoutWeight(1)
        Text('是否完成')
          .textAlign(TextAlign.Center)
          .fontSize(18)
          .layoutWeight(1)
        Text('操作')
          .textAlign(TextAlign.Center)
          .fontSize(18)
          .layoutWeight(1)
      }.width('100%')
      List() {
        ForEach(this.taskList, (item: TaskModel) => {
          ListItem() {
            Row() {
              Text(item.taskName)
                .textAlign(TextAlign.Center)
                .fontSize(18)
                .layoutWeight(1)
              Text(item.isFinish ? '已完成' : '未完成')
                .textAlign(TextAlign.Center)
                .fontSize(18)
                .fontColor(item.isFinish ? Color.Green : Color.Red)
                .layoutWeight(1)
              Button('完成')
                .visibility(item.isFinish ? Visibility.Hidden : Visibility.Visible)
                .onClick(() => {
                  this.changeFinished(item.tid,true)
                })
              Button('删除')
                .onClick(() => {
                  this.delTask(item.tid)
                })
            }.width('100%')
          }
        })
      }
    }
  }
}

–src/main/ets/model/TaskModel.ets:页面设计的数据结构

@ObservedV2
export default class TaskModel {
  //任务ID
  tid:number = 0
  //任务名称
  taskName: string = 'Todo';
  //是否完成
  @Trace
  isFinish: boolean = false;

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

–src/main/ets/vm/TaskViewModel.ets:项目的交互逻辑组件

import TaskModel from "../model/TaskModel";
import { promptAction } from "@kit.ArkUI";

@ObservedV2
export class TaskViewModel {
  //最大ID,用于新增数据
  @Trace
  maxId: number = 0
  @Trace
  finishedCount:number = 0
  //需要显示的任务列表
  @Trace tasksList: Array<TaskModel> = []

  //接口获取数据,本次为演示无实际接口,暂时直接写死
  queryTaskList() {
    this.tasksList.push(new TaskModel(1, '吃饭', true))
    this.tasksList.push(new TaskModel(2, '睡觉', true))
    this.tasksList.push(new TaskModel(3, '打豆豆', false))
    this.maxId = 3
    this.finishedCount = 1
  }

  //计算未完成的个数
  unFinished(){
    this.finishedCount = 0
    console.log('xx数组长度:'+this.tasksList.length);
    for (let i = 0; i < this.tasksList.length; i++) {
      if (!this.tasksList[i].isFinish) {
        this.finishedCount++
      }
    }
  }

  //删除任务
  delTask(id: number) {
    for (let i = 0; i < this.tasksList.length; i++) {
      if (this.tasksList[i].tid === id) {
        this.tasksList.splice(i, 1)
        this.unFinished()
        return
      }
    }
  }

  //修改状态
  updateTaskFinished(id: number, finished: boolean) {
    for (let i = 0; i < this.tasksList.length; i++) {
      if (this.tasksList[i].tid === id) {
        this.tasksList[i].isFinish = finished
        this.unFinished()
        promptAction.showToast({ message: '修改了' })
        return
      }
    }
  }

  //新增任务
  addTask(name: string) {
    this.maxId++
    this.tasksList.push(new TaskModel(this.maxId,name,false))
    this.unFinished()
  }
}

更多关于HarmonyOS鸿蒙Next中MVVM模式(状态管理V2实现)的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

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


在HarmonyOS鸿蒙Next中,MVVM模式通过状态管理V2实现,主要依赖@State@Prop@Link等装饰器来管理UI状态。@State用于组件内部状态管理,@Prop用于父组件向子组件传递状态,@Link用于双向绑定。通过ViewModel层处理业务逻辑,View层负责UI展示,实现数据与UI的分离,提升代码可维护性和可测试性。

回到顶部