MVC MVP MVVM

LogicCraft
• 阅读 2586

参考:
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/...

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

1 MVC

1.1 MVC 调用关系

MVC MVP MVVM

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

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)。

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

1.3 MVC 优缺点

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

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

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

举个栗子,model 和 view 如下:
MVC MVP MVVM
MVC MVP MVVM

    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调用关系

MVC MVP MVVM

用户行为输入,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 调用关系

MVC MVP MVVM

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

3.2 双向绑定带来了什么

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

MVC MVP MVVM

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 臃肿的问题,当然编码也会很方便。

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Wesley13 Wesley13
3年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这