MVC与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。
  • 第二阶段,由于原生 API 不好用,还要考虑浏览器兼容性,jQuery 横空出世,以简洁的 API 迅速俘获了前端开发者的芳心:
  • 第三阶段,MVC 模式,需要服务器端配合,JavaScript 可以在前端修改服务器渲染后的数据。
  • 现在,随着前端页面越来越复杂,用户对于交互性要求也越来越高,想要写出 Gmail 这样的页面,仅仅用jQuery 是远远不够的。MVVM 模型应运而生。

MVVM 最早由微软提出来,它借鉴了桌面应用程序的 MVC 思想,在前端页面中,把 Model 用纯 JavaScript 对象表示,View 负责显示,两者做到了最大限度的分离。

MVVM的诞生

就像我们之前分析 MVC 是如何合理分配工作的一样,我们需要数据所以有了 M,我们需要界面所以有了 V,而我们需要找一个地方把 M 赋值给 V 来显示,所以有了 C,然而我们忽略了一个很重要的操作:数据解析。

在 MVC 出生的年代,手机 APP 的数据往往都比较简单,没有现在那么复杂,所以那时的数据解析很可能一步就解决了,所以既然有这样一个问题要处理,而面向对象的思想就是用类和对象来解决问题,显然 V 和 M 早就被定义死了,它们都不应该处理 “解析数据” 的问题,理所应当的,“解析数据”这个问题就交给 C 来完成了。

而现在的手机 App 功能越来越复杂,数据结构也越来越复杂,所以数据解析也就没那么简单了。如果我们继续按照 MVC 的设计思路,将数据解析的部分放到了 Controller 里面,那么 Controller 就将变得相当臃肿。

还有相当重要的一点:Controller 被设计出来并不是处理数据解析的。

  • 管理自己的生命周期;
  • 处理 Controller 之间的跳转;
  • 实现 Controller 容器。

这里面根本没有 “数据解析” 这一项,所以显然,数据解析也不应该由 Controller 来完成。

那么我们的 MVC 中,M、V、C 都不应该处理数据解析,那么由谁来呢?这个问题实际上在面向对象的时候相当好回答:既然目前没有类能够处理这个问题,那么就创建一个新的类出来解决不就好了?所以我们聪明的开发者们就专门为数据解析创建出了一个新的类:ViewModel。这就是 MVVM 的诞生。