首页 > JavaScript 阅读:7,280

MVC、MVP、MVVM的区别和联系(精讲版)

在开始正式讲解之前,先举一个例子,如图1所示。这是一个很简单的计数器,单击“减”按钮,数字就会减 1;单击“加”按钮,数字就会加 1。
简单的计数器
图1:MV 系列框架例子

接下来需要知道的是,在 MV 系列框架中,M 和 V 指 Model 层和 View 层,但是其功能会因为框架的不同而变化:
  • Model 层很好理解,就是存储数据;
  • View 层则是展示数据,读者能看见这个例子,完全就是因为存在 View 层。

虽然在不同的框架中, View 层和 Model 层的内容可能会有所差别,但是其基础功能不变,变的只是数据的传输方式。

下面就从这个例子开始了解 MV 系列框架的概念。

1. MVC 框架

MVC 框架是 MVC、MVP、MVVM 这3个框架中历史最悠久的。20 世纪 70 年代,施乐公司发明了 Smalltalk 语言,用来编写图形界面的应用程序,脱离了 DOS 系统,让系统可视化,不用一直看着黑白的界面。

在 Smalltalk 发展到 80 版本的时候,MVC 框架被一位工程师提出来,MVC 框架的出现在很大程度上降低了应用程序的管理难度,之后被广泛应用于构架桌面和服务器应用程序。MVC 框架如图2所示(实线表示调用,虚线表示通知)。

MVC框架图
图2:MVC 框架图

Controller 是 MVC 中的 C,指控制层,在 Controller 层会接收用户所有的操作,并根据写好的代码进行相应的操作——触发 Model 层,或者触发 View 层,抑或是两者都触发。

需要注意:Controller 层触发 View 层时,并不会更新 View 层中的数据,View 层中的数据是通过监听 Model 层数据变化而自动更新的,与 Controller 层无关。

MVC 框架流程如图3所示:
MVC框架流程图
图3:MVC 框架流程图

从图3中可以看出,MVC 框架主要有两个缺点:
  • MVC 框架的大部分逻辑都集中在 Controller 层,代码量也都集中在 Controller 层,这带给 Controller 层很大的压力,而已经有独立处理事件能力的 View 层却没有用到。
  • 还有一个问题,就是 Controller 层和 View 层之间是一一对应的,断绝了 View 层复用的可能,因而产生了很多冗余代码。

为了解决以上问题,MVP 框架被提出来。

2. MVP 框架

首先需要知道,MVP 不是指 Most Valuable Player,而是指 Model-View-Presenter。

MVP 框架比 MVC 框架大概晚出现 20 年,1990 年,MVP 由 IBM 的子公司 Taligent 公司提出,它最开始好像是一个用于 C++ CommonPoint 的框架,这种说法正确与否这里不做考证,先来看一下 MVP 框架图(图4)。

MVP框架图
图4:MVP框架图

在 MVC 框架中,View 层可以通过访问 Model 层来更新,但在 MVP 框架中,View 层不能再直接访问 Model 层,必须通过 Presenter 层提供的接口,然后 Presenter 层再去访问 Model 层。

这看起来有点多此一举,但用处着实不小,主要有两点:
  • 首先是因为 Model 层和 View 层都必须通过 Presenter 层来传递信息,所以完全分离了 View 层和 Model 层,也就是说,View 层与 Model 层一点关系也没有,双方是不知道彼此存在的,在它们眼里,只有 Presenter 层。
  • 其次,因为 View 层与 Model 层没有关系,所以 View 层可以抽离出来做成组件,在复用性上比 MVC 模型好很多。

MVP 框架流程如图5所示:
MVP框架流程图
图5:MVP框架流程图

从图5中可以看出,View 层与 Model 层确实互不干涉,View 层也自由了很多。但还是有问题,因为 View 层和 Model 层都需经过 Presenter 层,致使 Presenter 层比较复杂,维护起来会有一定的问题。而且因为没有绑定数据,所有数据都需要 Presenter 层进行“手动同步”,代码量比较大,虽然比 MVC 模型好很多,但也是有比较多的冗余部分。

为了让 View 层和 Model 的数据始终保持一致,避免同步,MVVM 框架出现了。

3. MVVM 框架

MVVM 最早是由微软在使用 Windows Presentation Foundation 和 SilverLight 时定义的,2005 年微软正式宣布 MVVM 的存在。VM 是 ViewModel 层,ViewModel 层把 Model 层和 View 层的数据同步自动化了,解决了 MVP 框架中数据同步比较麻烦的问题,不仅减轻了 ViewModel 层的压力,同时使得数据处理更加方便——只需告诉 View 层展示的数据是 Model 层中的哪一部分即可。

MVVM 框架如图6所示:
MVVM框架图
图6:MVVM 框架图

读者可能感觉 MVVM 的框架图与 MVP 的框架图相似,确实如此,两者都是从 View 层开始触发用户的操作,之后经过第三层,最后到达 Model 层。但是关键问题是这第三层的内容, ViewModel 层双向绑定了 View 层和 Model 层,因此,随着 View 层的数据变化,系统会自动修改 Model 层的数据,反之同理。而 Presenter 层是采用手动写方法来调用或者修改 View 层和 Model 层,两者孰优孰劣不言而喻。

MVVM 框架流程图如图7所示:
MVVM框架流程图
图7:MVVM 框架流程图

从图7可以看出,View 层和 Model 层之间数据的传递也经过了 ViewModel 层, ViewModel 层并没有对其进行“手动绑定”,不仅使速度有了一定的提高,代码量也减少很多,相比于 MVC 和 MVP,MVVM 有了长足的进步。

至于双向数据绑定,可以这样理解:双向数据绑定是一个模板引擎,它会根据数据的变化实时渲染。这种说法可能不是很恰当,但是很好理解,如图8所示。

数据绑定概念
图8:数据绑定概念

如图8所示,View 层和 Model 层之间的修改都会同步到对方。

MVVM 模型中数据绑定方法一般有以下3种:
  • 数据劫持
  • 发布-订阅模式
  • 脏值检查

Vue.js 使用的是数据劫持和发布-订阅模式两种方法。

首先来了解三个概念:
  • Observer:数据监听器
  • Compiler:指定解析器
  • Watcher:订阅者

Observer 用于监听数据变化,如果数据发生改变,不论是在 View 层还是 Model 层, Oberver 都会知道,然后告诉 Watcher。Compiler 的作用是对数据进行解析,之后绑定指定的事件,在这里主要用于更新视图。

Vue.js 数据绑定的流程:首先将需要绑定的数据用数据劫持方法找出来,之后用 Observer 监听这堆数据,如果数据发生变化,Observer 就会告诉 Watcher,然后 Watcher 会决定让哪个 Compiler 去做出相应的操作,这样就完成了数据的双向绑定。

4. MVC、MVP 和 MVVM三者的区别和优劣

详细了解 MV 系列框架之后,相信读者已经了解 MVC、MVP、MVVM 这三者的优劣了。其实从 MVC 到 MVP 再到 MVVM,是一个不断进步的过程,后两者都是在 MVC 的基础上做的变化,使 MVC 更进一步,使用起来也更加方便。

MVC、MVP、MVVM 三者的主要区别就在于除 View 层和 Model 层之外的第三层,这一层的不同使得 MV 系列框架区分开来。

其实很难说出 MVC、MVP、MVVM 哪一个更好,从表面上看,显然是 MVVM 最好,使用起来更方便,代码相对也较少。但问题是 MVVM 的框架体积较大,相比于 MVC 的不用框架、MVP 的 4KB 框架,MVVM 遥遥领先。虽然 MVVM 框架可以单独引用,但现在更多使用前端脚手架工具进行开发,并且使用打包工具,这样一来,它跟 MVC 相比,体积是天差地别。

虽然机能过剩更令人放心,但是轻巧一些的框架会令项目锦上添花。所以要根据实际项目的需求来选择 MVC、MVP、MVVM,只有最适合的模式才是最好的框架。

每项新技术都要经历一个从一开始不被大众认可到后来人尽皆知的过程,其实就是一个改变的过程。只要这个框架能跟上时代的潮流,满足人们开发的需求,这就是一个合适的框架。

因此,如果你想真正从事开发这一行业(尤其是前端),需要拥有一颗不惧变化的心。

关注微信公众号「站长严长生」,在手机上阅读所有教程,随时随地都能学习。本公众号由C语言中文网站长运营,每日更新,坚持原创,敢说真话,凡事有态度。

魏雪原二维码
微信扫描二维码关注公众号