作者: 麦乐
不知道看了多少遍有关三者区别的文章,每个都是有图有真相,但是当被问起三者的区别,还是觉得说不清楚,因为没有真正的理解。
MVC
如下图,View和Controler都可以访问Model,Model中数据流动方法都是双向的。也就是说V和C都可以改变数据,也可以获取数据。
上图在代码层面表现如下:
基本结构:
- function createMVC() {
- var MVC = {};
- MVC.model = function() {
-
- }
- MVC.view = function() {
-
- }
- MVC.controler = function() {
-
- }
- }
比如说要实现一个新闻列表模块,实现数据层:
- function createMVC() {
- var MVC = {};
- MVC.model = function() {
- var M = {}
- // 通常是从后端获取的
- M.data = {
- newsList = [
- {
- text: '新闻一',
- icon: '',
- url: 'https://www.baidu.com'
- },
- {
- text: '新闻二',
- icon: '',
- url: 'https://blog.csdn.net'
- }
- ]
- }
- M.config= {
- // 新闻动画控制数据
- }
- return {
- getData: function(key) {
- return M.data[key]
- },
- setData: function(key, value) {
- M.data[key] = value;
- return this;
- },
- getConfig: function(key) {
- return M.config[key]
- },
- setConfig: function(key, value) {
- M.config[key] = value;
- return this;
- }
-
- }
- }()
- MVC.view = function() {
-
- }
- MVC.controler = function() {
-
- }
- }
实现视图层,负责根据数据生产html模版:
- MVC.view = function() {
- var M = MVC.model;
- var V = {
- createNewsList: function() {
- var html = '';
- var data = M.getData('newsList');
- if(!(data && data.length)) return;
- // 创建视图容器
- var dom = $.create('div', {
- class: 'news-contanier'
- })
- // 创建视图容器模版
- var tp1 = {
- container: [
- '<ul class="news-content">{#content#}</ul>'
- ].join(''),
- item: [
- "<li class='news-item'>",
- "<a href='{#url#}'></a>",
- "<span>{#text}</span>",
- "</li>",
- ].join('')
- }
- for(var i = 0; i < data.length; i++) {
- html += $.formateString(tp1.item, data[i])
- }
- dom.html($.formateString(tp1.container, {content: html})).appendTo('body')
- }
- };
- return function(v) {
- V[v]()
- }
- }()
实现控制层,调用上一层的生产html功能,添加需要的业务逻辑:
-
- MVC.controler = function() {
- var newsListData = MVC.model.getData('newsList');
- var renderNewsList = MVC.view('createNewsList');
- var C = {
- initNewsList: function() {
- renderNewsList();
- $('li','news-list').on('mouseover', function() {
- // 处理逻辑交互
- this.addClass('show')
- })
- }
- }
- c.initNewsList()
- }()
这样很好的做到了数据层,试图层,控制层(业务逻辑)的分离。这就是经典的MVC模型,这么看是不是更好理解一些。
总结:
优点:
1.各施其职,互不干涉
在MVC模式中,三个层各施其职,所以如果一旦哪一层的需求发生了变化,就只需要更改相应的层中的代码而不会影响到其它层中的代码。
2.有利于开发中的分工
在MVC模式中,由于按层把系统分开,那么就能更好的实现开发中的分工。网页设计人员可以进行开发视图层中的JSP,对业务熟悉的开发人员可开发业务层,而其它开发人员可开发控制层。
3.有利于组件的复用
分层后更有利于组件的复用。如控制层可独立成一个能用的组件,视图层也可做成通用的操作界面。
缺点:
1.视图和控制器联系紧密,耦合性比较大,没有控制器就无法生成视图。视图的大部分交互也都在控制层实现。
2.数据流向难以控制,视图层和控制层都可以获取数据,改变数据。
3.增加了结构复杂度。
MVP
View层不直接访问数据层,而是通过对Presenter(管理器层)实现对Model数据的访问。
基本结构:
- (function(window) {
- var MVP = function() {};
- MVP.model = function() {};
- MVP.view = function() {};
- MVP.presenter = function() {};
- // MVP入口
- MVP.init = function() {};
- // 可以全局访问
- window.MVP = MVP;
-
- })(window)
数据层跟MVC中类似:
-
- MVC.model = function() {
- var M = {}
- // 通常是从后端获取的
- M.data = {
- newsList = [
- {
- text: '新闻一',
- icon: '',
- url: 'https://www.baidu.com'
- },
- {
- text: '新闻二',
- icon: '',
- url: 'https://blog.csdn.net'
- }
- ]
- }
- M.config= {
- // 新闻动画控制数据
- }
- return {
- getData: function(key) {
- return M.data[key]
- },
- setData: function(key, value) {
- M.data[key] = value;
- return this;
- },
- getConfig: function(key) {
- return M.config[key]
- },
- setConfig: function(key, value) {
- M.config[key] = value;
- return this;
- }
-
- }
- }()
view层跟原来大不一样,不再直接访问数据,而是根据管理层传递进来的字符串转化为需要的模版,再暴露给管理器:
- MVP.view = function() {
- return function(str) {
- // 此处省略N行代码html
- return html
- }
- }();
上面返回函数的功能就是将类似这样的参数:
'li.news-item>a[href=@url]+span{@text}'
转化为类似这样的模版:
- [
- "<li class='news-item'>",
- "<a href='{#url#}'></a>",
- "<span>{#text}</span>",
- "</li>",
- ].join('')
大致实现一下管理层:
- MVP.presenter = function() {
- var V = MVP.view;
- var M = MVP.model;
- var C = {
- new: function(M, V) {
- var data = M.getData();
- var tp1 = V('li.news-item>a[href=@url]+span{@text}');
- $.create('ul', {
- class: 'news-ul'
- }).html(
- A.formartString(tp1,data)
- ).appendTo('#container')
- }
- }
- return {
- init: function() {
- for(var key in C) {
- C[key] && C[key](M, V, key)
- }
- },
- add: function(key, fun) {
- C[key] = fun;
- return this;
- }
-
- }
- }();
优点:
1)降低耦合度
(2)模块职责划分明显
(3)代码复用
(4)代码灵活性
MVP的缺点:
由于对视图的渲染放在了Presenter中,所以视图和Presenter的交互会过于频繁。如果Presenter过多地渲染了视图,往往会使得它与特定的视图的联系过于紧密。一旦视图需要变更,那么Presenter也需要变更了。
MVVM
这种模式为试图层定做了一套视图模型(ViewModel),并在视图模型中创建属性和方法,为视图层绑定数据并实现交互。上面所说的控制器或者管理器就是MVVM模型中的ViewModel。
Model层依然是服务端返回的数据模型。而ViewModel充当了一个UI适配器的角色,也就是说View中每个UI元素都应该在ViewModel找到与之对应的属性。除此之外,从Controller抽离出来的与UI有关的逻辑都放在了ViewModel中,这样就减轻了Controller的负担。
把Model和View关联起来的就是ViewModel。ViewModel负责把Model的数据同步到View显示出来,还负责把View的修改同步回Model。
优点:
- 低耦合:解耦视图和逻辑
- 独立开发
- 数据双向绑定,保证了数据的一致性
- 简单易学
缺点:
- 数据的双向绑定导致View不容易复用
- 模块比较大的话占用的内存也比较大