开天辟地 HarmonyOS(鸿蒙) - 状态管理: MVVM

源码 https://github.com/webabcd/HarmonyDemo
作者 webabcd

开天辟地 HarmonyOS(鸿蒙) - 状态管理: MVVM

示例如下:

pages\state\mvvm\MVVMDemo.ets

/*
 * mvvm - model, view ,viewmodel
 *   model - 负责数据的获取和存储,以及业务逻辑等,不与 view 关联
 *   view - 负责用户界面的展现,以及用户的输入等,不与 model 关联
 *   viewmodel - 是连接 model 和 view 的桥梁
 *     负责将 model 的数据转为 view 的数据,并管理用户界面状态
 *     负责处理用户的交互逻辑,并将相关数据交由 model 处理
 */

import { TaskListViewModel } from './viewmodel/MyViewModel';
import MyTopView from './view/MyTopView';
import MyListView from './view/MyListView';
import MyBottomView from './view/MyBottomView';
import { TitleBar } from '../../TitleBar';
import { LoadingDialog } from '@kit.ArkUI';

@Entry
@ComponentV2
struct MVVMDemo {

  @Local taskList: TaskListViewModel = new TaskListViewModel()

  loading: CustomDialogController = new CustomDialogController({
    builder: LoadingDialog({ content: 'loading' }),
  })

  async aboutToAppear() {
    this.loading.open()
    await this.taskList.loadTasks();
    this.loading.close()
  }

  get taskCount(): number {
    return this.taskList.tasks.length
  }

  build() {
    Column({space:10}) {
      TitleBar()
      MyTopView({ taskCount: this.taskCount })
      MyListView({ taskList: this.taskList });
      MyBottomView({ taskList: this.taskList });
    }
    .margin({left:10,right:10})
  }
}

pages\state\mvvm\model\MyModel.ets

export class MyData {
  tasks: ITaskModel[] = [];

  constructor() {
  }

  async loadTasks() {
    await new Promise<void>(r => setTimeout(r, 1000));
    this.tasks.push({name:"task 1", done:false})
    this.tasks.push({name:"task 2", done:false})
    this.tasks.push({name:"task 3", done:false})
  }

  addTask(name: string, done: boolean) {

  }

  remove(name: string) {

  }

  updateAllTaskDone(done: boolean) {

  }

  updateTask(name: string, done: boolean) {

  }
}

export interface ITaskModel {
  name: string;
  done: boolean;
};

pages\state\mvvm\view\MyTopView.ets

@ComponentV2
export default struct MyTopView {

  @Param taskCount: number = 0;

  build() {
    Column() {
      Text(`任务总数: ${this.taskCount}`)
    }
  }
}

pages\state\mvvm\view\MyBottomView.ets

import { TaskViewModel, TaskListViewModel } from '../viewmodel/MyViewModel';

@ComponentV2
export default struct MyBottomView {

  @Param taskList: TaskListViewModel = new TaskListViewModel();
  @Local newTaskName: string = '';

  build() {
    Column({space:10}) {
      Row() {
        Button('全部完成', { buttonStyle: ButtonStyleMode.NORMAL })
          .onClick(() => {
            this.taskList.updateAllTaskDone(true)
          })
        Blank(10)
        Button('全部未完成', { buttonStyle: ButtonStyleMode.NORMAL })
          .onClick(() => {
            this.taskList.updateAllTaskDone(false)
          })
      }

      Row() {
        TextInput({ placeholder: '添加新任务', text: $$this.newTaskName }).layoutWeight(1)
        Blank(10)
        Button('+', { buttonStyle: ButtonStyleMode.NORMAL })
          .onClick(() => {
            let newTask = new TaskViewModel(this.newTaskName, false);
            this.taskList.addTask(newTask);
            this.newTaskName = '';
          })
      }
    }
  }
}

pages\state\mvvm\view\MyListView.ets

import { TaskViewModel, TaskListViewModel } from '../viewmodel/MyViewModel';

@ComponentV2
struct MyListItem {

  @Param task: TaskViewModel = new TaskViewModel('', false);
  @Event deleteTask: () => void = () => {};
  @Event updateTask: () => void = () => {};

  build() {
    Row({space:10}) {
      Image($r('app.media.app_icon')).width(24).height(24)
      Text(this.task.name).fontSize(20)
      Blank(10)
      Button('删除').onClick(() => this.deleteTask())
    }
    .width('100%')
    .height(50)
    .padding({left:10, right:10})
    .backgroundColor(this.task.done ? '#FFA500' : '#99f1f1f1')
    .borderRadius(10)
    .onClick(() => {
      this.task.done = !this.task.done
      this.updateTask()
    })
  }
}

@ComponentV2
export default struct MyListView {
  @Param taskList: TaskListViewModel = new TaskListViewModel();

  build() {
    Repeat<TaskViewModel>(this.taskList.tasks)
      .each((obj: RepeatItem<TaskViewModel>) => {
        MyListItem({
          task: obj.item,
          deleteTask: () => this.taskList.removeTask(obj.item),
          updateTask: () => this.taskList.updateTask(obj.item),
        })
      })
  }
}

pages\state\mvvm\viewmodel\MyViewModel.ets

import { MyData, ITaskModel } from '../model/MyModel';

@ObservedV2
export class TaskViewModel {
  @Trace name: string = '';
  @Trace done: boolean = false;
  public constructor(name: string, done: boolean) {
    this.name = name;
    this.done = done;
  }
}

@ObservedV2
export class TaskListViewModel {

  myData = new MyData();

  @Trace tasks: TaskViewModel[] = [];

  async loadTasks() {
    await this.myData.loadTasks()
    for(let task of this.myData.tasks){
      let taskViewModel = new TaskViewModel(task.name, task.done);
      this.tasks.push(taskViewModel)
    }
  }

  updateAllTaskDone(done: boolean): void {
    this.myData.updateAllTaskDone(done)
    for(let task of this.tasks){
      task.done = done;
    }
  }

  addTask(task: TaskViewModel): void {
    this.myData.addTask(task.name, task.done)
    this.tasks.push(task);
  }

  removeTask(task: TaskViewModel): void {
    this.myData.remove(task.name)
    this.tasks.splice(this.tasks.indexOf(task), 1)
  }

  updateTask(task: TaskViewModel): void {
    this.myData.updateTask(task.name, task.done)
  }
}

源码 https://github.com/webabcd/HarmonyDemo
作者 webabcd

posted @ 2025-02-05 14:10  webabcd  阅读(177)  评论(0)    收藏  举报