浅谈MV*模式
最近想总结一下前端中的MV*(MVC、MVP、MVVM)模式。
但是,鉴于自己的理解还是比较局限,我想在此转Livoras的一篇博客。
本文对这篇博客的观点比较赞同,并且引用了该文章的图片。大家可以不必展开我的文章,直接读这一篇大作。
原文链接:界面之下:还原真实的MV*模式。
注:本文有图,但是由于网络原因,图片未能上传,后续补上。:smile:
MV*模式解决什么问题
简而言之,我认为MV*就是实现了领域模型数据和UI层的解耦。
但是MVC、MVP、MVVM对其解耦的思路的不同。从历史的角度来看,MVC、MVP和MVVM是一种进化的关系。但是鉴于项目的规模以及模式实现的方式不同,不同的MV*模式各有其优点和缺点,难分孰好孰坏。
但是业界越来越认为:MVVM是前端领域最好的MV*模式。
下面我就分别谈一下这三种模式。
MVC模式
MVC模式的应用程序,除了有UI层(View)和领域模型(Model)之外,多加了一层Controller。他们之间的关系是这样的:
用户对View的输入等操作并不会在View的相关模块中处理逻辑,而是由Controller层获得这些操作(所谓的Pass Call),并由Controller层对这些操作中的数据经过应用逻辑的操作,然后在调用Model层的接口,将数据交给Model层。Model层执行与业务逻辑相关的操作,并更新数据。Model和View通过观察者模式联系在一起,即View是Model的观察者,当Model数据变动之后,通知View层进行数据更新。
我们看到MVC是一个单向的三角关系。
总的来说:
Model主要是与业务数据有关。
View是应用程序数据的可视化表示。
Controller管理应用程序中Model和View之间的逻辑和协调。
View了解Controller,Controller了解Model,而View能够直接访问Model。
MVP模式
MVP比起MVC模式,它的特点很明显。MVP中M和V之间的依赖关系被消除了。
在MVC中,M和V之间通过观察者模式依赖。这种依赖关系在MVP中被转移到M和P层中。这样一来P层必须通过一定的机制通知V层进行数据的更新。所以MVP模式中V层中提供了供P层调用的接口。P层作为观察者获得数据变化是,将调用V层的接口将变化反映到V层中。
总的来说,MVP中:
Model层依然是主要与业务数据有关。
View依然是应用程序的可视化表示,但是在MVP中它对领域数据(Model层)完全无知,比起MVC中View层更轻了。
Presenter层比较重,它不仅调用Model的接口,也调用View的接口。而且需要作为观察者获得Model的数据更新。
MVVM模式
最后来看下MVVM模式:
MVVM模式中,M层数据的变化不是通过观察者模式通知到V层的(即没有M和V的依赖),也不是通过VM层调用V层的接口将数据传递给V层的(这意味着用户代码不需要手动更新V层)。而是通过在VM层实现一个特殊的binder,将数据从M层直接绑定到V层。这样ViewModel层了解Model层,View层了解ViewModel层。
ViewModel充当了一个数据转换器的作用。它将Model信息转换为View信息,还将命令从View传递到Model。在这里,View可以访问ViewModel,ViewModel可以访问Model。
我理解的ViewModel是:
ViewModel为View提供了一个访问Model的桥梁,但是View不是直接访问Model层。ViewModel为View提供了Model的特定于View的子集,可以包含状态和逻辑信息,而且无需向View暴露整个Model。
View和ViewModel通过数据绑定和事件可以进行通信,因为ViewModel可以访问Model层,所以ViewModel为了数据绑定要暴露Model中的部分属性。
关于业务逻辑,很多前端框架都单独做了一个与MVVM无关的Service层,将业务逻辑放到Service层中,由ViewModel调用。即:View => ViewModel => Service这样一个流向。
对于双向绑定《界面之下》是这么描述的:
双向数据绑定。可以简单而不恰当地理解为一个模版引擎,但是会根据数据变更实时渲染。
其实我不是很确定这样理解对不对。
不过双向绑定带来了一个缺点,那就是数据绑定的声明是指令式地写在View的模版当中的,这些内容是没办法去打断点debug的。
一个很浅显的困惑
吐个槽而已
MVC、MVVM等高大上的词汇,从我开始接触web开发的时候就不绝于耳。开始使用ExtJS4.2的时候,“大神”告诉我这是一个实现了MVC模式的框架。然后还很耐心的告诉我:MVC有三层,它们分别放在不同的文件夹下。这个XX.view.js实现了View层,这个XX.Model.js实现了Model层,这个XX.controller.js实现了Controller层。
后来,我开始对Vue.js感兴趣。我告诉“大神”说这是个MVVM模式的框架。他也很兴奋,指着我的代码兴冲冲的问我:你写这些个东西,哪个是Model呢?我也被问蒙了,对啊,Model在哪呢?
直到我不再跟着“大神”干活之后,我才发现,那些话都是狗屁。
(我没有说谁坏话的意思。也可能是我对他的话有误解,所以才造成了我现在的困惑。)
MV*框架和用户代码
诚然,框架帮我们实现了MV模式,不代表我们写的代码也是按照MV模式组织的。因为我们使用了框架,本身就意味着我们认同它的架构和模式,然后调用框架的API,来实现业务层代码。因此即使用户代码中出现类似vm,view等等的命名,也不代表这段代码就是MV*中某一层的实现,而更像是对某一层的实现的一个扩展。而且不同的模式下的用户代码量级确实有时会有显著差距。
再总结以下三点:
MV模式的框架 + 用户代码 约== MV模式的软件
MV模式的框架,是MV模式的一个实现。
模式提供的通用解决方案,其记录方式并不与某个特定问题挂钩(《JavaScript设计模式》, O'RELLY出版)。
结束
最后再吐槽一下:《JavaScript设计模式》这本书,翻译的真心不太好,我真的读不通顺。
一点微小的见解,多多指正。
完。
关键字:mvc, mvvm, MVP, 设计模式
版权声明
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!