MVC MVP MVVM

参考:
MVC,MVP 和 MVVM 的图示 - 阮一峰
http://www.ruanyifeng.com/blo...
Web开发的MVVM模式
http://www.cnblogs.com/dxy198...
界面之下:还原真实的MV*模式
https://segmentfault.com/a/11...
Angular沉思录(一)数据绑定
https://github.com/xufei/blog...
深刻理解JavaScript系列(32):设计模式之观察者模式
http://www.cnblogs.com/TomXu/...javascript

MVC/MVP/MVVM 在不少博问中都有整理,这里我根据阅读博文和本身的理解,梳理一下 web 前端 html、css、javascript 中的他们。css

1 MVC

1.1 MVC 调用关系

clipboard.png

用户行为输入,View 传递给 Controller(在JS中经过事件监听实现);Controller 进行应用逻辑处理,调用 Model 暴露的接口方法操做 Model;View 与 Model 间为观察者模式,Model 更新完数据后通知 View 更新。html

JS中的观察者模式 - 汤姆大叔博文,本文阐述了如何在JS中实现观察者模式:观察者模式中 Model 通知 View 更新,其实是 Model 对订阅了本身的 View 提供操做方法的调用。前端

1.2 经典MVC的JS编码理解

View,View 包含2部分:1)实现界面展现的 html+css;2)对外暴露的操做 View 的方法。
View -> Controller,用户行为从视图传递至控制器,有两种方法:1)经过 html 标签的事件属性如 onclick;2)JS中的addEventListener(非IE)/ attachEvent(IE)方法。(如JQuery的bind和angular的ng-click等都是对原生方法的封装,等效于上述方法)
Controller,当视图发生用户行为输入时候,会进入控制器中的事件回调函数,在回调函数中,通常会对界面数据进行预处理(如:输入校验)、应用逻辑处理(如:界面显示Loading),而后调用对应的 Model 方法进行模型更新操做。
Controller -> Model,Controller 的事件回调函数中调用 Model 的操做方法。
Model,Model 可理解为一个对象,对象的属性就是抽象的数据模型,对象的方法就是对 Controller 暴露的操做方法。
Model -> View,Model 更新 View 使用观察者模式,从JS实现上来讲 Model 有个数组队列中保存着订阅(subscribe)了本身 View 的更新方法,Model 更新完毕后,遍历并调用数组中的 View 更新方法即为发布(publish)。java

OK,这就是 HTML+CSS+JS 实现 经典MVC 的一个流程,下面咱们说说它的优缺点。git

1.3 MVC 优缺点

优势:
1)职责分离思想,MVC三者各司其职,模块化;
2)观察者模式,实现单个Model可更新多视图更新。github

职责分离的优势不用多说,代码清晰易维护;观察者模式实现单个数据模型,可同时更新多个视图,扩展性良好。web

缺点:
1)View依赖Model,不可避免引入业务逻辑,不易复用。segmentfault

举个栗子,model 和 view 以下:
clipboard.png
clipboard.png设计模式

    model 仅有 good/middle/bad 3种数据,view 基于此数据,需扩展颜色、图例描述等系列业务逻辑,经典MVC中,view 对外暴露渲染饼图的方法,颜色这些业务的东东就被包含进去了,这就是咱们说的不可避免引入业务逻辑。假设如今有新的 model2 含3种商品数量(颜色用黄、绿、蓝),要复用饼图 view,咱们很容易想到,在 view 与 model 间加一层模型转换就能很实现复用,可是经典MVC中,model 与 view 之间是观察者模式,那么模型转换只能放到 view 中(model 通常不变),view 得扩展个新方法来知足 model2。
    这个简单例子也许不能很充分说明 View 依赖 Model 形成的问题,但可设想若是 View 的业务逻辑和应用功能十分复杂,那么要适配不一样的Model必然形成 View 的臃肿,必定程度后便难以复用。

2 MVP

我理解,如今你们常说起的 MVC 实际就是 MVP,它刷新界面通常遵循 V -> P -> M -> P -> V 的步骤。(MVP 模式将 Controller 更名为 Presenter,可等同视之)

2.1 MVP调用关系

clipboard.png

用户行为输入,View 传递给 Presenter(在JS中经过事件监听实现);Presenter 进行应用逻辑处理,调用 Model 暴露的接口方法操做 Model;Model 更新完数据后传递给 Presenter(异步 Model 操做可以使用 promise,让Presenter在回调函数中得到最新数据),Presenter 处理最新数据,调用 View 暴露的接口方法更新 View。

2.2 MVP的JS编码理解

MVP 完全分离了 View 与 Model,使用 HTML+CSS+JS 编码,移除 MVC 观察者模式,其他都很容易理解,在此再也不赘述。

2.3 MVP 优缺点

优势:
1)解决View与Model耦合问题,使View变薄,更易复用。

请对应参考上面 MVC 中的缺点1的例子。使用 MVP 后,Presenter 做为 View 和 Model 的中间层,那么 View 和 Model 仅需对外暴露标准接口,模型转换的那些事儿,所有能够交给Presenter,View 层变薄,更容易复用。

缺点:
1)Presenter 承担了V->M和M->V的应用和业务逻辑,容易变得臃肿,可维护性下降。

3 MVVM(以Angular1.x为例)

3.1 MVVM 调用关系

clipboard.png

MVVM 模式实际就是将 MVP 中的 Presenter 更名为 ViewModel,调用过程基本一致,最大的改良是 ViewModel 间的双向绑定。

3.2 双向绑定带来了什么

这里以实际项目中用过的 Angular1.x 为例,下图仅为示意便于理解。

clipboard.png

View 和 ViewModel 间,有一个对象 $scope,ViewModel 能够操做修改 $scope.data,View html 使用 $scope.data。当 ViewModel 设置 $scope.data=123 时,Angular框架会自动刷新 View 的显示 123,同理当界面有 input 这样的入口时,修改 data 时,Angular框架也会自动刷新到 $scope.data 中。【优势】View 和 ViewModel 间的数据同步功能,部分被 Angular 框架承担,部分解决了 MVP 中 Presenter 臃肿的问题,固然编码也会很方便。