当前位置: 首页 > news >正文

MVC 与 MVVM 区别 - 鸿蒙

一、MVC 架构

1. 角色定义

  • Model(数据模型):管理数据、业务逻辑、网络请求、数据库操作等
  • View(视图):负责 UI 展示,接收用户操作并抛出事件,不包含业务逻辑
  • Controller(控制器):作为调度中心,处理用户交互、调用 Model、更新 View

2. 目录结构

src/main/ets/
├── model/
│   └── DataModel.ets
├── view/
│   └── MyView.ets
└── pages/└── Index.ets          // 作为 Controller

3. 代码示例

Model

export class DataModel {getInfo(): string {return "鸿蒙 MVC 标准架构";}
}

View

@Component
export struct MyView {@Prop content: string;onButtonClick?: () => void;build() {Column() {Text(this.content).fontSize(28).margin(15)Button("点击获取数据").onClick(() => {this.onButtonClick?.();})}}
}

Controller(主页面)

import { DataModel } from '../model/DataModel';
import { MyView } from '../view/MyView';@Entry
@Component
struct Index {private dataModel: DataModel = new DataModel();@State showText: string = "请点击按钮";build() {Column() {MyView({content: this.showText,onButtonClick: () => {this.showText = this.dataModel.getInfo();}})}.width('100%').height('100%').justifyContent(FlexAlign.Center)}
}

4. 执行流程

  1. 用户在 View 上点击
  2. View 将事件抛给 Controller
  3. Controller 调用 Model 获取数据
  4. Controller 更新 @State 状态,View 自动刷新

5. 流程图

┌─────────────┐        ┌─────────────┐        ┌─────────────┐
│    View     │───────▶│ Controller  │───────▶│    Model    │
│ 自定义UI组件  │   事件  │    主页面    │   调用  │  数据模型    │
└─────────────┘        └─────────────┘        └─────────────┘▲                                                  ││               返回数据                            │└──────────────────────────────────────────────────┘

二、MVVM 架构

1. 角色定义

  • Model(数据模型):数据、业务逻辑、网络请求、数据库操作
  • View(页面/组件):只负责 UI 显示,不包含业务逻辑
  • ViewModel(视图模型):核心枢纽,管理状态、处理逻辑、提供数据绑定,自动驱动 UI 更新

2. 目录结构

src/main/ets/
├── model/
│   └── DataModel.ets
├── viewmodel/
│   └── DataViewModel.ets
├── view/
│   └── NewMyView.ets
└── pages/└── Index.ets          // 仅作为入口,不再承担控制器职责

3. 代码示例

Model

export class DataModel {getInfo(): string {return "鸿蒙 MVVM 自动绑定!";}
}

ViewModel

import { DataModel } from '../model/DataModel';export class DataViewModel {private model: DataModel = new DataModel();message: string = "等待点击";fetchData() {this.message = this.model.getInfo();}
}

View

import { DataViewModel } from '../viewmodel/DataViewModel';@Component
export struct NewMyView {@Link vm: DataViewModel;build() {Column() {Text(this.vm.message).fontSize(30).margin(20)Button("获取数据").onClick(() => {this.vm.fetchData();})}.justifyContent(FlexAlign.Center)}
}

主页面(入口)

import { DataViewModel } from '../viewmodel/DataViewModel';
import { NewMyView } from '../view/NewMyView';@Entry
@Component
struct Index {@State vm: DataViewModel = new DataViewModel();build() {Column() {NewMyView({ vm: this.vm })}.width('100%').height('100%')}
}

4. 执行流程

  1. View 触发点击,调用 ViewModel 的方法
  2. ViewModel 调用 Model 获取数据
  3. Model 返回数据,ViewModel 更新内部状态
  4. View 通过数据绑定自动刷新(无需手动操作)

5. 流程图

┌──────────┐      双向绑定      ┌────────────┐      ┌──────────┐
│   View   │◄──────────────────►│ ViewModel  │◄────►│   Model  │
│  页面UI  │   数据自动同步更新   │  状态+逻辑  │      │  数据层   │
└──────────┘                    └────────────┘      └──────────┘

三、MVC vs MVVM 核心区别

对比维度 MVC MVVM
数据流 单向:View → Controller → Model → 手动更新 View 双向绑定:View ↔ ViewModel,数据变化自动驱动 UI
职责划分 Controller 承担调度、更新 UI、调用 Model,易臃肿 ViewModel 专注状态与逻辑,View 仅负责展示,职责单一
依赖关系 View 依赖 Controller,Controller 依赖 Model View 依赖 ViewModel,ViewModel 依赖 Model,View 与 Model 完全隔离
可测试性 需要模拟 UI 环境,测试成本较高 ViewModel 无 UI 依赖,可用单元测试直接验证
代码量 随业务增长,Controller 代码膨胀,维护成本上升 通过数据绑定减少模板代码,状态集中管理

四、总结与选型建议

1. 核心理念对比

  • MVC:手动调度,Controller 作为“中间人”协调 View 与 Model,适合逻辑简单的场景。
  • MVVM:自动绑定,ViewModel 作为“桥梁”连接 View 与 Model,通过数据驱动 UI,代码更解耦、更易维护。

2. 鸿蒙开发中的实践

  • 鸿蒙 ArkUI 采用 声明式 UI,天然契合 MVVM 思想。通过 @State@Link@Provide 等装饰器,可以轻松实现数据与视图的双向同步。
  • 推荐在复杂业务中使用 MVVM 模式,将状态提升到 ViewModel,保持 View 的纯净与可复用性。

3. 如何选择

  • 如果你的页面逻辑非常简单(如仅展示静态数据),MVC 足够。
  • 一旦涉及表单交互、状态共享、多组件通信或复杂业务逻辑,建议使用 MVVM,它将大幅提升代码的可维护性和可测试性。
http://www.jsqmd.com/news/517723/

相关文章:

  • 用Python搞定交通流量预测:从数据清洗到LSTM建模的保姆级实战(附明尼苏达州数据集)
  • 小程序毕业设计springboot基于微信小程序的同城上门遛喂宠物系统
  • 7za极简移植指南:5分钟为树莓派编译轻量版7zip
  • EXPERIMENTAL RESULTS
  • 手把手复现TomoSAR仿真实验:基于Python的压缩感知三维成像全流程(附DEM对比)
  • Android地图开发踩坑记:从MapLibre Native集成到成功显示第一个Marker的完整流程
  • ZYNQ DMA数据传输实战:从PL到PS的调试与优化
  • 避开这5个坑,你的FreeModbus移植才算成功 | 基于FreeRTOS的实战经验
  • GPU内存访问的隐藏陷阱:为什么你的CUDA程序跑得不够快?
  • Chromium ARM交叉编译实战:用x86主机为飞腾电脑打包浏览器(含硬件加速配置)
  • 深入解析nslookup命令:从基础查询到高级DNS诊断
  • 实测IQuest-Coder-V1-40B:代码生成效果展示与作品分享
  • 改稿速度拉满!AI论文平台 千笔写作工具 VS Checkjie,专为毕业论文全流程设计
  • OneAPI开源大模型网关核心能力解析:为什么它成为开发者首选
  • Nanbeige 4.1-3B开源大模型部署案例:低成本GPU运行3B参数JRPG前端实录
  • 飞书机器人实战:5分钟搞定图片消息发送(含token获取避坑指南)
  • 【教程】2026年3月OpenClaw(Clawdbot)京东云1分钟保姆级集成方法
  • Qwen3.5-9B开发者案例:基于7860端口构建内部知识库问答系统
  • Android 项目依赖结构树可视化:Gradle 与 Android Studio 实战指南
  • 保姆级避坑指南:在Ubuntu 22.04上搞定Vitis AI 2.5 Docker环境(含国内源配置)
  • VidorBoot:Arduino MKR Vidor 4000 FPGA引导位流解析
  • 用遗传算法(GA)攻克分布式置换流水车间调度问题(DPFSP)
  • 【CP AUTOSAR】CanIf(CAN Interface)配置实践与核心机制解析
  • 从哈工大数据结构期末算法题出发:手把手教你用Python实现“删K位得最小数”和“二叉树最长路径”
  • 安卓7.0系统深度解锁:安全获取Root权限的实用指南
  • 72×40 OLED轻量库:SSD1315驱动与I²C高效显存优化
  • 【最全】2026年3月OpenClaw(Clawdbot)腾讯云10分钟喂饭级搭建指南
  • SOONet模型与卷积神经网络(CNN)特征提取器的协同优化
  • 5分钟搞定Microchip dsPIC33串口通信:MCC配置全流程+避坑指南
  • 腾讯AI Lab的WebVoyager如何像真人一样浏览网页?多模态Agent实战解析