博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
实例说明MVC,MVP,MVVM架构
阅读量:4561 次
发布时间:2019-06-08

本文共 3963 字,大约阅读时间需要 13 分钟。

很早就知道有这三个概念,但是一直都不清楚是怎么回事,在网上搜索,都是泛泛而谈,没有具体例子,新手是看不懂的,直到找到,我对这三个架构有了更清楚的了解。

从一个简单的例子去研究这三个架构。

注意,MVC,MVP,MVVM中的C,P,VM,下文都要controller指代。

需求如下

界面上显示100,以及两个按钮,其中一个点一下加1,另外一个点一下减1

如图

诚然,这么简单的需求,并不需要用什么架构去完成,可是如果是复杂的需求,要长篇大论才能说完,所以只拿简单的来做例子,实际开发中,你在完成一个需求之前,是需要好好掂量是否要用架构,要的话,用什么架构(不局限于这三个),架构里面又要用什么设计模式等等。经过我的实践,发现,即使是架构改变了,view是可以完全不变的,所以先展现view层的代码。

html部分

100

js部分

function $(id) {  return document.querySelector(`#${id}`);}function View(controller) {  const upBtn = $('upBtn');  const downBtn = $('downBtn');  const textSpan = $('text');  this.render = function(model) {    textSpan.innerHTML = model.getValue();  }  upBtn.onclick = controller.up;  downBtn.onclick = controller.down;}

render方法是核心,方法名称不能改(后面要依赖这个render方法),其中要实现数据的展示逻辑,然后是一些点击事件的绑定

MVC

model层

function Model() {  let value = 100;  this.up = function() {    value += 1;  };  this.down = function() {    value -= 1;  };  this.getValue = function() {    return value;  };}

保存数据,并提供访问,修改数据的方法,如果仅仅是这样,那么当model改变时,view是不知道的,所以需要让model去通知view,我数据改变了,你要更新了。怎么做呢?利用观察者模式。在model中,增加一个数组views,去保存这个model对应的视图,在修改数据的时候,遍历views数组,调用每个view的render方法,参数是自己。

修改后的model

function Model() {  let value = 100;  const self = this;  const views = [];  this.up = function() {    value += 1;  };  this.down = function() {    value -= 1;  };  this.getValue = function() {    return value;  };  this.broadcast = function() {    views.forEach(view => view.render(self));  };  this.subscribe = function(cb) {    views.push(cb);  }}

仔细看修改后的model,虽然增加了通知的方法(broadcast),但是在修改数据的方法(up和down)中并没有去通知视图。这个工作是由controller承担的,另外把view注册到model中,也是controller做的。

controller层

function Controller() {  let view = null;  let model = null;  this.up = function() {    // 修改数据    model.up();    // 通知视图    model.broadcast();  };  this.down = function() {    model.down();    model.broadcast();  }  this.init = function() {    view = new View(this);    model = new Model();    // 把视图注册到model中    model.subscribe(view);  }}

可以看到,controller把自己传给了view去创建视图,同时保存引用,创建model后,把view注册到model中。同时实现了,改变数据,通知视图的工作。

请一定要好好理解MVC,后面的MVP,MVVM都只是稍加修改而已。

MVP

在MVC中,改变数据,通知视图,都是在controller做的,注册视图,以及通知视图,这两个方法的实现,都是model完成的,既然model负责数据处理,这两个工作实际上和改变数据是没关系的,把他们都转移到controller中,不仅可以让model层专注于数据处理,同时也方便多个视图共用一个controller

model层

function Model() {  let value = 100;  this.up = function() {    value += 1;  };  this.down = function() {    value -= 1;  };  this.getValue = function() {    return value;  };}

model层更小了,删除了注册,通知方法,只保存数据和提供获取,修改数据的方法

controller层

function Controller() {  let views = [];  let model = null;  function broadcast() {    views.forEach(view => view.render(model));  }  this.up = function() {    model.up();    broadcast();  };  this.down = function() {    model.down();    broadcast();  }  this.init = function() {    views.push(new View(this));    model = new Model();  }}

controller,增加了广播方法,该方法的实现和调用都在controller中,另外,如果想多个视图共用一个controller,如果这多个视图都是同一个model,上面代码能够胜任,如果是这多个视图是不同的model,那就要自己去实现好view和model的对应关系了(要用map来存储对应关系,一个数组做不到)。

MVVM

可以看到,在MVP中,model也有一个up方法,controller也有一个up方法,只是增加了一个广播方法的调用。是不是有些重复呢?把这两个类似的方法整合到controller,model只负责保存数据,不实现修改数据的逻辑,这就是MVVM了,极大地精简model

model层

function Model() {  let value = 100;  this.getValue = function() {    return value;  };  this.setValue = function(v) {    value = v;  }}

其实,不用函数,单纯地用一个变量,也是可以的,但是为了view层不变,view层中依赖model的getValue方法,所以这里还是用函数去实现model

controller层

function Controller() {  let views = [];  let model = null;  function broadcast() {    views.forEach(view => view.render(model));  }  this.up = function() {    model.setValue(model.getValue() + 1);    broadcast();  };  this.down = function() {    model.setValue(model.getValue() - 1);    broadcast();  }  this.init = function() {    views.push(new View(this));    model = new Model();  }}

精简model的代价是controller要做更多的事情,实现修改数据的逻辑,通知视图。如果用框架,react或者vue,通知视图这部分框架会帮你实现,只要实现数据修改的逻辑就好了。

至此,三个架构都讲完了,如果错误,欢迎讨论。

代码可在上下载,需要node环境。

参考资料:http://www.cnblogs.com/zhouyangla/p/6936455.html

转载于:https://www.cnblogs.com/maoscut/p/7623462.html

你可能感兴趣的文章
spark计算平均值
查看>>
Thread
查看>>
Chrome浏览器安装插件时一直停留在"正在检查"的可用解决方法
查看>>
XPath
查看>>
【问底】徐汉彬:亿级Web系统搭建——单机到分布式集群(三)
查看>>
关于struts2的Unable to load configuration. - Class: java.net.Plain
查看>>
java分布式锁的处理
查看>>
350. Intersection of Two Arrays II java solutions
查看>>
[bzoj1485] [HNOI2009]有趣的数列
查看>>
【#】Spring3 MVC 注解(一)---注解基本配置及@controller和 @RequestMapping 常用解释...
查看>>
本地文本数据查询
查看>>
多语言的2种实现方式对比
查看>>
BZOJ4810 Ynoi2017由乃的玉米田(莫队+bitset)
查看>>
Java学习(十)
查看>>
[转]这才是真正的3D显示!Leap Motion推出次毫米级3D手动控制技术,让人手和影像融为一体...
查看>>
10月27日体会目标
查看>>
c# 前台js 调用后台代码
查看>>
2017-02-20 可编辑div中如何在光标位置添加内容
查看>>
$.ajax()方法详解
查看>>
day42
查看>>