MVVM、MVP、MVC
目录
MVVM
MVVM 将应用程序清晰地划分为三个核心部分
MVVM 的核心机制:数据绑定
MVVM 的工作流程
MVVM 的优势
前端框架与 MVVM
MVP
MVP核心组成部分:三位一体
MVP 的工作流程
MVP 的优势
MVP模式与MVVM模式在数据绑定方面的区别
MVC
核心组成部分:三位一体
MVC 的工作流程
MVC 的优势
MVVM
MVVM 是一种软件架构模式。
MVVM 将应用程序清晰地划分为三个核心部分
Model(模型):代表应用程序的数据和业务逻辑。
内容:业务数据、状态以及操作这些数据的业务规则。
特点:
-
对 View 和 ViewModel 完全不可知。
-
通常是独立且可复用的单元。
-
可以来源于本地状态、后端 API、本地存储等。
View(视图):定义应用程序的用户界面结构和外观。
内容:由HTML、CSS以及用于动态渲染的模版语法构成。主要关注如何将数据呈现给用户,以及如何捕获用户输入。
特点:
- 理想情况下,不包含任何业务逻辑或直接操作数据的代码。
- 点击事件梳理、表单提交等行为应该委托给ViewModel。
- 通过声明式绑定与 ViewModel 连接。声明式意味着你告诉框架“这里显示什么数据”或“当用户点击这个按钮时调用什么方法”,而不是手动写代码去操作 DOM 元素。
ViewModel(视图模型):作为Model和View之间的桥梁和协调者。他是MVVM模式的核心。
内容:
- 包含了View的状态;
- 暴露了View可用的数据;
- 包含了View可调用的命令和方法;
- 监听Model的变化并且更新暴露给View的数据;
- 处理用户输入,更新自身状态或调用Model进行业务处理;
- 实现数据绑定的绑定目标;
特点:
- 对View是高度是高度适配的。他专门为特定的View设计,提供View所需的数据和命令的精确接口。
- 完全不知道View的具体实现细节(如DOM结构、CSS类名)。只关心暴露的数据和命令。
- 与Model交互,但不直接操作DOM。
MVVM 的核心机制:数据绑定
- 声明式绑定:在View的模版中,使用特殊的语法(如Vue中{{ }},v-bind,v-model)声明式的绑定到ViewModel的属性或方法上。
- 双向数据绑定:
ViewModel -> View: 当 ViewModel 中的状态数据发生变化时,框架自动更新所有绑定到该数据的 View 元素。
View -> ViewModel: 当用户在 View 中进行输入(如在文本框输入、选择下拉框)时,这些变化自动更新到绑定的 ViewModel 属性上。
-
单向数据流 :数据从父组件(可以视为更高层的 ViewModel)流向子组件(View)。子组件通过回调函数(由父组件/ViewModel 提供)通知父组件状态变化,父组件更新状态后重新渲染子组件。
MVVM 的工作流程
- 用户与View交互( 用户点击一个按钮或在输入框中输入文字 )
- View通知ViewModel( 按钮的点击事件或输入框的输入事件通过数据绑定自动调用 ViewModel 中对应的命令或更新 ViewModel 的属性 )
- ViewModel处理交互( 可能执行一些简单的 UI 逻辑;可能需要调用 Model 中的业务逻辑;Model 处理完业务逻辑后,可能会更新自身的数据 )
- View自动更新(由于数据绑定,View 中所有绑定到 ViewModel 变化了的数据的 UI 元素,都会由框架自动更新以反映最新状态。)
MVVM 的优势
- Model、View、ViewModel 职责清晰,互不干扰。
- 代码结构清晰,可维护性高
- 可测试性高
- 数据驱动视图
前端框架与 MVVM
Vue.js: 被认为是最典型的 MVVM 框架。
Angular: 采用组件化架构,组件类扮演了 ViewModel 的角色(包含数据、逻辑),模板使用声明式绑定。其变更检测机制是实现数据绑定的核心。
React: 本身更专注于 View 层(“V” in MVC/MVVM),强调组件化和单向数据流。
MVP
MVP 是 MVC模式的一个衍生变体,提升 View 的可测试性。
MVP核心组成部分:三位一体
Model(模型):代表应用程序的核心数据、业务规则和状态。负责数据的获取(API、本地存储)、存储、验证和业务逻辑处理。
特点:
-
对 View 和 Presenter 完全不可知。
-
纯粹的领域逻辑和数据。
View(视图): 负责定义用户界面的结构和外观,以及捕获用户输入。
特点:
- 定义接口:view需要实现一个又Presenter定义的接口。这个接口声明了 Presenter 可以调用哪些方法来更新 UI 以及 View 会触发哪些事件通知 Presenter 用户交互发生了
- 被动性:View 通常是被动的。它通过接口暴露的方法被 Presenter 更新,并通过接口定义的事件/回调通知 Presenter 用户的操作。
- 不知道Model
- 不知道Presenter的具体实现
Presenter(表示器): View 和 Model 之间的协调者。
内容:响应用户交互;与Model交互;准备数据给View;更新View;管理视图逻辑。
特点:
- 持有 View 和 Model 的引用
- 包含大部分应用逻辑
- 可测试性高
MVP 的工作流程
-
用户与 View 交互: 用户点击按钮。
-
View 通知 Presenter: View 的实现捕获到这个点击事件,并调用它持有的
IPresenter
接口上的对应方法(如presenter.handleSaveClick()
)。View 自身不处理点击逻辑。 -
Presenter 处理事件
Presenter 的handleSaveClick
方法被调用
Presenter 可能需要从 View 获取当前输入数据(通过调用IView
上的getFormData()
方法)
Presenter 可选地进行一些简单的数据验证或格式化 -
Model 执行业务逻辑: Model 处理保存请求(如验证数据、调用 API),完成后通知 Presenter(通常通过回调、Promise 或事件)。
Presenter 调用 Model 的方法执行业务逻辑(如model.saveUser(formData)
) -
Presenter 处理 Model 结果并更新 View:
Presenter 接收到 Model 操作的结果(成功或失败,以及相关数据/错误信息)。
Presenter 格式化结果数据(如果需要)。
Presenter 调用 View 的IView
接口方法(如view.showSuccessMessage("Saved!")
或view.showError("Save failed: " + error)
)来更新 UI。
Presenter 可能还会调用其他方法更新状态(如view.setLoading(false)
)。
MVP 的优势
- 极高的可测试性
- 清晰的职责分离
- 框架无关性:
MVP 是一种设计模式,不依赖于特定框架,可以在原生 JavaScript 或任何前端库/框架中实现。
MVP模式与MVVM模式在数据绑定方面的区别
模式 | 数据绑定机制 | 数据流 | 核心特点 | 技术依赖 | 数据绑定相关风险 |
---|---|---|---|---|---|
MVP | 手动绑定 | 单向主导: - Model → Presenter → View(数据展示) - View → Presenter → Model(用户交互) | 双向同步需要手动实现 | 无特殊要求,可在任何平台实现 | 1.内存泄漏 2.样板代码过多 |
MVVM | 自动绑定 | 双向绑定: - ViewModel ⇄ View(通过绑定器自动同步) | 声明式绑定、双向同步自动化 | 需要框架提供数据绑定引擎(如 Vue.js、Angular) | 1.过度绑定导致性能问题 2.调试困难 |
MVC
MVC 的核心目标是将应用程序的数据处理(Model)、用户界面(View) 和控制逻辑(Controller) 分离,以提高代码的可维护性、可复用性和可测试性。
核心组成部分:三位一体
Model(模型): 代表应用程序的核心数据、状态和业务逻辑。
内容:
- 数据本身(如用户信息、产品列表)。
- 操作数据的业务规则(如数据验证、计算、持久化逻辑 - 与数据库/API 交互)。
- 状态管理(如购物车状态、登录状态)。
特点:
- 独立:对 View 和 Controller 完全不可知。
- 可通知: 通常提供一种机制(如观察者模式)来通知其他组件(主要是 View)其状态的变化。
- 可复用:可以在不同的视图或上下文中使用。
View(视图):负责数据的可视化呈现,即用户看到的界面。
内容:由 UI 元素(HTML, CSS, 模板)构成,定义如何将 Model 数据渲染给用户。
特点:
- 被动:理想情况下,其主要工作是渲染 Model 的数据
- 观察Model:在经典 MVC 中,View 订阅 Model 的变化通知。当 Model 状态改变时,View 会自动更新自身以反映最新数据。
- 数量: 一个 Model 可以有多个 View 以不同方式显示相同数据。
Controller (控制器):作为用户交互的入口点,充当 Model 和 View 之间的协调者。
内容:
-
接收用户输入事件。
-
解释用户输入(例如,将点击事件映射到具体的业务操作)。
-
根据输入操作 Model(调用 Model 的方法更新数据或状态)。
-
可能选择或更新 View(尤其是在涉及多个视图或导航的场景中)。
特点:
-
响应式: 由用户输入驱动。
-
连接器: 知道如何与 Model 交互(调用其方法)以及如何影响 View(有时是直接通知 View 更新,有时是通过 Model 变化间接触发 View 更新)。
-
不负责渲染
MVC 的工作流程
-
用户交互: 用户与 View 进行交互(例如,点击界面上的按钮)。
-
事件路由: 用户交互事件(如点击)首先被发送到 Controller。
-
Controller 处理输入:
Controller 接收到事件
Controller 解释事件(识别出用户点击了“保存”按钮)
Controller 操作 Model: 根据解释的结果,调用相应的 Model 方法 -
Model 更新与通知:
Model 执行业务逻辑(如验证数据、保存到数据库)
Model 的状态/数据发生变化
Model 通知所有注册观察它的组件(主要是 View)发生了变更 -
View 更新:
View(作为 Model 的观察者)接收到 Model 变更的通知
View 主动从 Model 中获取最新的数据
View 更新自身的 UI 以反映 Model 的最新状态
MVC 的优势
- 将数据管理、UI 展示和用户交互控制分开
- Model可以在多个 View 和 Controller 中复用;如果设计得当,可以绑定到不同的 Model 上显示数据。
- 修改 Model 逻辑通常不会直接影响 View
- Model 包含核心业务逻辑和数据,独立于 UI,易于进行单元测试。
- 一个 Model 的状态变化可以自动同步到多个不同的 View。