首先我们简要讨论下MVC,MVP,MVVM框架模型
一、MVC(Model-View-Controller)
MVC是比较直观的架构模式,用户操作->View(负责接收用户的输入操作)->Controller(业务逻辑处理)->Model(数据持久化)->View(将结果反馈给View)。
- M-Model : 业务逻辑和实体模型
- V-View : 布局文件
- C-Controller : 控制器
该框架虽然也是把代码逻辑和UI层分离,但是View层能做的事情还是很少的,很多对于页面的呈现还是交由C实现,这样会导致项目中C的代码臃肿,如果项目小,代码臃肿点还是能接受的,但是随着项目的不断迭代,代码量的增加,你就会没办法忍受该框架开发的项目,这时MVP框架就应运而生。
二、MVP(Model-View-Presenter)
MVP是把MVC中的Controller换成了Presenter(呈现),目的就是为了完全切断View跟Model之间的联系,由Presenter充当桥梁,做到View-Model之间通信的完全隔离。
- M-Model : 业务逻辑和实体模型
- V-View : 布局文件
- P-Presenter : 完成View和Model的交互
MVP框架相对于MVC框架做了较大的改变,代替MVC框架中的C的是P,对比MVC和MVP的模型图可以发现变化最大的是View层和Model层不在直接通信,所有交互的工作都交由Presenter层来解决。既然两者都通过Presenter来通信,为了复用和可拓展性,MVP框架基于接口设计的理念大家自然就可以理解其用意。
但MVP框架也有不足之处:
1.接口过多,一定程度影响了编码效率。
2.业务逻辑抽象到Presenter中,较为复杂的界面代码量依然会很多。
3.导致Presenter的代码量过大。
三、MVVM(Model-View-ViewModel)
如果说MVP是对MVC的进一步改进,那么MVVM则是思想的完全变革。它是将“数据模型数据双向绑定”的思想作为核心,因此在View和Model之间没有联系,通过ViewModel进行交互,而且Model和ViewModel之间的交互是双向的,因此视图的数据的变化会同时修改数据源,而数据源数据的变化也会立即反应到View上。
- M-Model : 实体模型
- V-View : 布局文件
- VM-ViewModel : DataBinding所在之处,对外暴露出公共属性,View和Model的绑定器
对比MVP和MVVM模型图可以看出,他们之间区别主要体现在以下两点:
可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多View重用这段视图逻辑。
低耦合。以前把数据填充到View,还要进行一些视图逻辑。现在这些都可在布局中完成。
MVC、MVP、MVVM这些模式是为了解决开发过程中的实际问题而提出来的,目前作为主流的几种架构模式而被广泛使用。
四、前端中的MVVM
在彻底了解MVVM之前,我们先回顾一下前端发展的历史。
在上个世纪的1989年,欧洲核子研究中心的物理学家Tim Berners-Lee发明了超文本标记语言(HyperText Markup Language),简称HTML,并在1993年成为互联网草案。从此,互联网开始迅速商业化,诞生了一大批商业网站。
最早的HTML页面是完全静态的网页,它们是预先编写好的存放在Web服务器上的html文件。浏览器请求某个URL时,Web服务器把对应的html文件扔给浏览器,就可以显示html文件的内容了。
如果要针对不同的用户显示不同的页面,显然不可能给成千上万的用户准备好成千上万的不同的html文件,所以,服务器就需要针对不同的用户,动态生成不同的html文件。一个最直接的想法就是利用C、C++这些编程语言,直接向浏览器输出拼接后的字符串。这种技术被称为CGI:Common Gateway Interface。
很显然,像新浪首页这样的复杂的HTML是不可能通过拼字符串得到的。于是,人们又发现,其实拼字符串的时候,大多数字符串都是HTML片段,是不变的,变化的只有少数和用户相关的数据,所以,又出现了新的创建动态HTML的方式:ASP、JSP和PHP——分别由微软、SUN和开源社区开发。
在ASP中,一个asp文件就是一个HTML,但是,需要替换的变量用特殊的<%=var%>标记出来了,再配合循环、条件判断,创建动态HTML就比CGI要容易得多。
但是,一旦浏览器显示了一个HTML页面,要更新页面内容,唯一的方法就是重新向服务器获取一份新的HTML内容。如果浏览器想要自己修改HTML页面的内容,就需要等到1995年年底,JavaScript被引入到浏览器。
有了JavaScript后,浏览器就可以运行JavaScript,然后,对页面进行一些修改。JavaScript还可以通过修改HTML的DOM结构和CSS来实现一些动画效果,而这些功能没法通过服务器完成,必须在浏览器实现。
用JavaScript在浏览器中操作HTML,经历了若干发展阶段:
第一阶段,直接用JavaScript操作DOM节点,使用浏览器提供的原生API:
var dom = document.getElementById('name');
dom.innerHTML = 'Homer';
dom.style.color = 'red';
第二阶段,由于原生API不好用,还要考虑浏览器兼容性,jQuery横空出世,以简洁的API迅速俘获了前端开发者的芳心:
$('#name').text('Homer').css('color', 'red');
第三阶段,MVC模式,需要服务器端配合,JavaScript可以在前端修改服务器渲染后的数据。
现在,随着前端页面越来越复杂,用户对于交互性要求也越来越高,想要写出Gmail这样的页面,仅仅用jQuery是远远不够的。MVVM模型应运而生。
MVVM最早由微软提出来,它借鉴了桌面应用程序的MVC思想,在前端页面中,把Model用纯JavaScript对象表示,View负责显示,两者做到了最大限度的分离。
把Model和View关联起来的就是ViewModel。ViewModel负责把Model的数据同步到View显示出来,还负责把View的修改同步回Model。
ViewModel如何编写?需要用JavaScript编写一个通用的ViewModel,这样,就可以复用整个MVVM模型了。
一个MVVM框架和jQuery操作DOM相比有什么区别?
我们先看用jQuery实现的修改两个DOM节点的例子:
<!-- HTML -->
<p>Hello, <span id="name">Bart</span>!</p>
<p>You are <span id="age">12</span>.</p>
Hello, Bart!
You are 12.
用jQuery修改name和age节点的内容:
'use strict';
----
var name = 'Homer';
var age = 51;
$('#name').text(name);
$('#age').text(age);
----
// 执行代码并观察页面变化
如果我们使用MVVM框架来实现同样的功能,我们首先并不关心DOM的结构,而是关心数据如何存储。最简单的数据存储方式是使用JavaScript对象:
var person = {
name: 'Bart',
age: 12
};
我们把变量person看作Model,把HTML某些DOM节点看作View,并假定它们之间被关联起来了。
要把显示的name从Bart改为Homer,把显示的age从12改为51,我们并不操作DOM,而是直接修改JavaScript对象:
Hello, Bart!
You are 12.
'use strict';
----
person.name = 'Homer';
person.age = 51;
----
// 执行代码并观察页面变化
执行上面的代码,我们惊讶地发现,改变JavaScript对象的状态,会导致DOM结构作出对应的变化!这让我们的关注点从如何操作DOM变成了如何更新JavaScript对象的状态,而操作JavaScript对象比DOM简单多了!
这就是MVVM的设计思想:关注Model的变化,让MVVM框架去自动更新DOM的状态,从而把开发者从操作DOM的繁琐步骤中解脱出来!