ArkTS中的MVC、MVP、MVVM
在 ArkTS 和 ArkUI 开发中一个页面通常包含三部分内容页面展示用户交互数据请求和业务处理。如果所有代码都写在一个Component中随着功能增加组件会变得越来越臃肿。MVC、MVP 和 MVVM 的作用就是将页面、业务和数据进行合理拆分。本文使用同一个“登录页面”来理解这三种架构。一、三种架构共同解决的问题假设登录页面需要完成以下功能获取用户输入的账号和密码校验账号和密码调用登录接口显示加载状态显示登录成功或失败登录成功后跳转页面。如果这些逻辑全部写在页面组件中EntryComponentstruct LoginPage{Stateaccount:stringStatepassword:stringStateloading:booleanfalseStatemessage:stringprivateasynclogin():Promisevoid{// 参数校验// 网络请求// 错误处理// 页面状态修改// 页面跳转}build(){// 页面布局}}随着功能增加LoginPage会同时负责UI 布局状态管理输入校验网络请求数据转换错误处理页面跳转。这类组件通常被称为“胖组件”。MVC、MVP、MVVM 的核心目标就是让不同对象承担不同职责。二、公共的 Model 层无论采用哪种架构Model 的职责基本一致。Model 负责数据实体网络请求数据库存储业务数据处理底层服务能力。例如classUser{id:numbername:stringconstructor(id:number,name:string){this.ididthis.namename}}classLoginService{asynclogin(account:string,password:string):PromiseUser{if(accountadminpassword123456){returnnewUser(1,管理员)}thrownewError(账号或密码错误)}}LoginService只负责完成登录业务不关心页面中使用的是Text Button TextInput LoadingProgressModel 不应该依赖具体 UI。三、MVCController 直接协调 Model 和 ViewMVC 分为Model View Controller其中Model负责数据和业务能力View负责界面展示Controller接收用户事件调用 Model并更新 View。在 ArkUI 中Component经常同时承担 View 和 Controller 的职责build() → View 事件处理方法 → ControllerMVC 示例EntryComponentstruct LoginMvcPage{Stateaccount:stringStatepassword:stringStateloading:booleanfalseStatemessage:stringprivateloginService:LoginServicenewLoginService()privateasynconLoginClick():Promisevoid{if(this.account.length0){this.message请输入账号return}if(this.password.length6){this.message密码不能少于 6 位return}this.loadingtruethis.messagetry{constuserawaitthis.loginService.login(this.account,this.password)this.message欢迎你${user.name}}catch(error){this.message账号或密码错误}finally{this.loadingfalse}}build(){Column({space:16}){TextInput({placeholder:请输入账号,text:this.account}).onChange((value:string){this.accountvalue})TextInput({placeholder:请输入密码,text:this.password}).onChange((value:string){this.passwordvalue})Button(this.loading?登录中...:登录).enabled(!this.loading).onClick((){this.onLoginClick()})if(this.loading){LoadingProgress()}Text(this.message)}.padding(20)}}MVC 的数据流用户点击 ↓ View 触发事件 ↓ Controller 处理逻辑 ↓ Controller 调用 Model ↓ Model 返回结果 ↓ Controller 修改页面状态 ↓ View 重新渲染可以概括为View → Controller → Model View ← Controller ← ModelMVC 的特点MVC 最大的特点是Controller 直接读取 View 的数据也直接修改 View 的状态。例如this.loadingtruethis.message登录失败这种方式简单直接适合业务较少的页面。但页面复杂后Controller 逻辑容易全部堆积在组件中最终形成“胖组件”。四、MVPPresenter 通过接口命令 ViewMVP 分为Model View PresenterPresenter 可以理解为从 Controller 中抽离出来的业务协调者。它负责获取用户输入校验数据调用 Model处理业务结果命令 View 更新页面。MVP 的核心是Presenter 不直接操作具体 UI而是通过 View 接口控制页面。定义 View 接口interfaceLoginViewContract{getAccount():stringgetPassword():stringshowLoading():voidhideLoading():voidshowMessage(message:string):voidshowLoginSuccess(user:User):void}这个接口规定登录页面必须具备哪些能力。Presenter 只认识这个接口并不知道页面具体使用的是Text、Toast 还是 Dialog。Presenter 实现classLoginPresenter{privateview:LoginViewContractprivateloginService:LoginServiceconstructor(view:LoginViewContract,loginService:LoginService){this.viewviewthis.loginServiceloginService}asynclogin():Promisevoid{constaccountthis.view.getAccount()constpasswordthis.view.getPassword()if(account.length0){this.view.showMessage(请输入账号)return}if(password.length6){this.view.showMessage(密码不能少于 6 位)return}this.view.showLoading()try{constuserawaitthis.loginService.login(account,password)this.view.showLoginSuccess(user)}catch(error){this.view.showMessage(账号或密码错误)}finally{this.view.hideLoading()}}}Presenter 中没有出现任何 ArkUI 控件Component State TextInput Button Text因此 Presenter 可以脱离页面独立测试。MVP 页面EntryComponentstruct LoginMvpPage{Stateaccount:stringStatepassword:stringStateloading:booleanfalseStatemessage:stringprivatepresenter:LoginPresenter|nullnullaboutToAppear():void{constview:LoginViewContract{getAccount:():string{returnthis.account},getPassword:():string{returnthis.password},showLoading:():void{this.loadingtrue},hideLoading:():void{this.loadingfalse},showMessage:(message:string):void{this.messagemessage},showLoginSuccess:(user:User):void{this.message欢迎你${user.name}}}this.presenternewLoginPresenter(view,newLoginService())}build(){Column({space:16}){TextInput({placeholder:请输入账号,text:this.account}).onChange((value:string){this.accountvalue})TextInput({placeholder:请输入密码,text:this.password}).onChange((value:string){this.passwordvalue})Button(this.loading?登录中...:登录).enabled(!this.loading).onClick((){this.presenter?.login()})if(this.loading){LoadingProgress()}Text(this.message)}.padding(20)}}MVP 的数据流用户点击 ↓ View 将事件交给 Presenter ↓ Presenter 获取 View 输入 ↓ Presenter 调用 Model ↓ Model 返回结果 ↓ Presenter 调用 View 接口 ↓ View 修改页面状态 ↓ 页面重新渲染可以概括为View ↔ Presenter ↔ ModelMVP 的核心特征Presenter 会调用this.view.showLoading()this.view.showMessage(登录失败)this.view.showLoginSuccess(user)这些代码表达的是View请显示加载状态 View请显示错误信息 View请显示登录成功所以 MVP 的本质是Presenter 输出的是行为和命令。Presenter 虽然不认识具体控件但它知道 View 可以执行哪些操作。五、MVVMViewModel 提供页面状态MVVM 分为Model View ViewModelViewModel 负责保存页面状态接收页面输入处理输入校验调用 Model转换页面数据提供页面可以直接使用的状态。MVVM 的核心是ViewModel 不命令 View 做什么只修改自身状态View 根据状态重新渲染。ViewModel 实现ObservedclassLoginViewModel{account:stringpassword:stringloading:booleanfalsemessage:stringprivateloginService:LoginServiceconstructor(loginService:LoginService){this.loginServiceloginService}getloginEnabled():boolean{returnthis.account.length0this.password.length6!this.loading}setAccount(account:string):void{this.accountaccount}setPassword(password:string):void{this.passwordpassword}asynclogin():Promisevoid{if(this.account.length0){this.message请输入账号return}if(this.password.length6){this.message密码不能少于 6 位return}this.loadingtruethis.messagetry{constuserawaitthis.loginService.login(this.account,this.password)this.message欢迎你${user.name}}catch(error){this.message账号或密码错误}finally{this.loadingfalse}}}ViewModel 中没有Text Button TextInput LoadingProgress它只维护页面状态。MVVM 页面EntryComponentstruct LoginMvvmPage{StateviewModel:LoginViewModelnewLoginViewModel(newLoginService())build(){Column({space:16}){TextInput({placeholder:请输入账号,text:this.viewModel.account}).onChange((value:string){this.viewModel.setAccount(value)})TextInput({placeholder:请输入密码,text:this.viewModel.password}).onChange((value:string){this.viewModel.setPassword(value)})Button(this.viewModel.loading?登录中...:登录).enabled(this.viewModel.loginEnabled).onClick((){this.viewModel.login()})if(this.viewModel.loading){LoadingProgress()}Text(this.viewModel.message)}.padding(20)}}MVVM 的数据流用户输入或点击 ↓ View 调用 ViewModel ↓ ViewModel 调用 Model ↓ Model 返回结果 ↓ ViewModel 修改自身状态 ↓ View 读取新状态 ↓ 页面重新渲染可以概括为View ↔ ViewModel ↔ ModelMVVM 的核心特征ViewModel 只会修改this.loadingtruethis.message登录失败它不会调用this.view.showLoading()this.view.showMessage()View 根据状态决定页面如何显示if(this.viewModel.loading){LoadingProgress()}Text(this.viewModel.message)因此 MVVM 的本质是ViewModel 输出的是状态和数据。六、MVP 和 MVVM 的核心区别MVP 和 MVVM 都把业务逻辑从页面组件中抽离但它们与 View 的通信方式不同。MVPPresenter 命令 Viewthis.view.showLoading()this.view.showMessage(登录失败)Presenter 的意思是View你现在显示加载。 View你现在显示错误。Presenter 输出的是行为。MVVMViewModel 修改状态this.loadingtruethis.message登录失败ViewModel 的意思是我现在处于加载状态。 我现在有一条错误信息。View 根据这些状态决定如何渲染。ViewModel 输出的是状态。因此可以记住Presenter 输出行为 ViewModel 输出状态七、Model 和 ViewModel 的区别Model 表示真实业务数据。例如classUser{firstName:stringlastName:stringage:number0vip:booleanfalse}这些是服务器或数据库中的原始数据。但页面可能需要显示张三 18岁 VIP会员ViewModel 可以将 Model 转换成适合页面直接展示的数据classUserViewModel{displayName:stringageText:stringvipText:stringupdate(user:User):void{this.displayName${user.firstName}${user.lastName}this.ageText${user.age}岁this.vipTextuser.vip?VIP会员:普通用户}}所以Model真实业务数据 ViewModel页面需要的数据和状态八、三种架构的核心对比架构中间层业务逻辑位置UI 更新方式MVCControllerComponent 或 ControllerController 直接修改状态MVPPresenterPresenterPresenter 通过接口命令 ViewMVVMViewModelViewModelView 根据 ViewModel 状态渲染进一步理解问题MVCMVPMVVM谁处理点击事件ControllerPresenterViewModel谁执行输入校验ControllerPresenterViewModel谁调用 ModelControllerPresenterViewModel谁修改 UIControllerViewView中间层输出什么直接操作行为、命令状态、数据是否依赖状态绑定不强制不强制通常依赖测试难度相对较高较低较低九、ArkTS 项目应该如何选择简单页面使用 MVC例如关于页面静态详情页简单设置页只有少量状态和交互的页面。这类页面直接在 Component 中处理逻辑即可没必要创建大量额外对象。流程型页面适合 MVP例如多步骤注册实名认证权限申请复杂表单提交分步骤业务流程。这类页面经常需要明确控制 View显示下一步 隐藏当前区域 弹出错误提示 进入成功页面Presenter 输出行为会比较直观。状态复杂的页面适合 MVVM例如下载页面播放器页面聊天页面购物车页面股票行情页面多状态列表页面。这些页面通常有大量状态加载中 加载成功 加载失败 空数据 刷新中 是否可点击 下载进度 播放进度 未读数量MVVM 可以把这些状态集中放在 ViewModel 中由 View 声明式渲染。十、为什么 MVVM 与 ArkUI 很契合ArkUI 是声明式 UI。开发者不是一步一步命令页面创建 Loading 添加 Loading 隐藏按钮 修改文字 移除 Loading而是描述页面在某种状态下应该是什么样子if(this.viewModel.loading){LoadingProgress()}Button(登录).enabled(this.viewModel.loginEnabled)Text(this.viewModel.message)当状态变化时ArkUI 会重新计算和渲染相关 UI。这与 MVVM 的状态驱动思想天然一致ViewModel 管理状态 View 描述状态对应的界面十一、任何架构都可能变得臃肿MVC 可能出现Massive ComponentMVP 可能出现Massive PresenterMVVM 可能出现Massive ViewModel如果 ViewModel 同时负责网络请求数据库存储JSON 解析页面跳转权限申请埋点文件下载缓存处理页面状态那么它同样会非常臃肿。更合理的结构可以继续拆分为View ↓ ViewModel / Presenter ↓ UseCase / Service ↓ Repository ↓ 网络和数据库架构的重点不是类名而是职责是否清晰。十二、最终总结MVC、MVP 和 MVVM 都是在解决页面代码职责混乱的问题。MVCView 触发事件 → Controller 调用 Model → Controller 直接修改 View一句话总结Controller 直接协调 Model 和 View。MVPView 把事件交给 Presenter → Presenter 调用 Model → Presenter 通过接口命令 View一句话总结Presenter 不直接操作控件但会命令 View 做什么。MVVMView 把输入交给 ViewModel → ViewModel 调用 Model → ViewModel 修改状态 → View 根据状态重新渲染一句话总结ViewModel 不命令 View只提供 View 需要的状态。最终可以压缩为三句话MVCController 直接修改 View。 MVPPresenter 通过接口命令 View。 MVVMViewModel 修改状态View 根据状态自己更新。再进一步压缩MVC 直接协调 MVP 行为驱动 MVVM 状态驱动

相关新闻

寄存柜订单工单模块「三性六讲」演讲稿

寄存柜订单工单模块「三性六讲」演讲稿

问题 1:请介绍一下你最近做的项目?(需求)我近期落地的是智能寄存柜订单工单全套系统模块,整套系统面向车站、商圈网点寄存柜用户,支撑从下单寄存、订单查询、取件开柜、超时补缴、历史对账、异常售后全链路…

2026/7/30 13:42:47阅读更多 →
UE4 SteamVR开发实战:从环境配置到混合现实模拟器实现

UE4 SteamVR开发实战:从环境配置到混合现实模拟器实现

1. 项目概述:从蓝图到沉浸式体验的跨越最近几年,虚拟现实(VR)和混合现实(MR)的热度一直没降下来,从游戏娱乐到工业仿真,再到数字孪生,应用场景越来越广。作为一名在游戏和…

2026/7/30 13:40:46阅读更多 →
如何将开源的ppt-master接入智能体中

如何将开源的ppt-master接入智能体中

本文以claude code和WorkBuddy为例子,介绍如何将ppt-master 这个开源skill接入到智能体中。 第一步:下载技能 下载地址:https://gitee.com/zsz083/ppt-master git clone https://gitee.com/zsz083/ppt-master.git 如果没有安装git&#xf…

2026/7/30 13:40:46阅读更多 →
【AI 翻译】你到底该选哪类工具?套壳 / 表层 AI / 商用平台选型指南(避坑干货)

【AI 翻译】你到底该选哪类工具?套壳 / 表层 AI / 商用平台选型指南(避坑干货)

前几期,我们拆解了AI翻译的底层架构,实战对比了四类行业的翻译质量,也看清了格式还原这道“最后一公里”的鸿沟。相信你已经明白:套壳工具、表层AI、商用级平台之间,存在结构性的能力差距。 但还有个更实际的问题摆在…

2026/7/30 14:47:07阅读更多 →
深度解析DWMBlurGlass:Windows系统级模糊渲染技术实战指南

深度解析DWMBlurGlass:Windows系统级模糊渲染技术实战指南

深度解析DWMBlurGlass:Windows系统级模糊渲染技术实战指南 【免费下载链接】DWMBlurGlass Add custom effect to global system title bar, support win10 and win11. 项目地址: https://gitcode.com/gh_mirrors/dw/DWMBlurGlass DWMBlurGlass作为Windows系统…

2026/7/30 14:47:07阅读更多 →
C#与Lua热更新架构:原理、实现与Unity游戏开发实践

C#与Lua热更新架构:原理、实现与Unity游戏开发实践

1. 项目概述:为什么游戏需要“热更新”? 做游戏开发,尤其是手游和网游,最头疼的问题之一就是更新。想象一下,你刚上线一个版本,发现了一个致命的数值BUG,或者一个能让玩家卡出地图的恶性漏洞。按…

2026/7/30 14:47:07阅读更多 →
Ball Shear测试后铝Pad没有残金,是键合失效吗?推拉力测试机测试结果解析

Ball Shear测试后铝Pad没有残金,是键合失效吗?推拉力测试机测试结果解析

在半导体封装制造过程中,金线键合(Wire Bond)是实现芯片与外部电路连接的重要工艺。随着封装结构不断微型化,键合点的机械可靠性成为影响器件长期稳定运行的重要因素。 为了评价金线键合质量,工程中通常采用推拉力测试…

2026/7/30 14:47:07阅读更多 →
质量可靠的机械活性砂过滤器哪家好

质量可靠的机械活性砂过滤器哪家好

引言随着环保意识的增强和工业技术的进步,活性砂过滤器作为一种高效的水处理设备,在饮用水、工业用水及污水处理等领域得到了广泛应用。然而,面对市场上众多品牌和型号的选择,如何挑选一家质量可靠、性能稳定的活性砂过滤器供应商…

2026/7/30 14:47:07阅读更多 →
AI 驱动数据治理落地难?主流AI数据治理平台功能与适用场景盘点

AI 驱动数据治理落地难?主流AI数据治理平台功能与适用场景盘点

很多人让我介绍全域数据治理方案并推荐一些厂商?那么本次测评筛选国内6家主流商用数据治理平台,剔除单一工具型厂商,按照市场占有率、技术成熟度、智能化落地效果划分为三大梯队,梯队内不分先后,评估标尺沿用五大核心评…

2026/7/30 14:45:06阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/29 9:47:45阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/30 12:22:27阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/29 7:58:51阅读更多 →
3分钟解锁iOS应用自由:TrollInstallerX让你的iPhone摆脱安装限制 [特殊字符]

3分钟解锁iOS应用自由:TrollInstallerX让你的iPhone摆脱安装限制 [特殊字符]

3分钟解锁iOS应用自由:TrollInstallerX让你的iPhone摆脱安装限制 🚀 【免费下载链接】TrollInstallerX A TrollStore installer for iOS 14.0 - 16.6.1 项目地址: https://gitcode.com/gh_mirrors/tr/TrollInstallerX 你是否曾经因为iOS系统的严格…

2026/7/30 0:00:58阅读更多 →
[GESP202606 四级] 扫雷

[GESP202606 四级] 扫雷

B4557 [GESP202606 四级] 扫雷 https://www.luogu.com.cn/problem/B4557 中国计算机学会(CCF)2026年6月C四级讲解——扫雷 https://www.bilibili.com/video/BV1MCMg6AEXR/ B4557 [GESP202606 四级] 扫雷 https://www.bilibili.com/video/BV1ZKTj6ZEVh/ 2…

2026/7/30 0:00:58阅读更多 →
Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 您是否曾因Windows系统盘空间不足而烦恼?是否遇到过设…

2026/7/30 0:00:58阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/30 0:27:26阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/30 4:47:18阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/29 14:26:42阅读更多 →