MVVM(Model View ViewModel)是一种基于MVC的设计,开发人员在HTML上写一些Bindings,利用一些指令绑定,就能在Model和ViewModel保持不变的情况下,很方便的将UI设计与业务逻辑分离,从而大大的减少繁琐的DOM操作。

起源

MVVM这个概念最是在2005年,由微软的工程师John Grossman在其博客中提出,最初这个概念是用在微软的WPF上的。直到最近几年,MVVM这种设计才被Javascript所实现,并产生了许多框架,如 KnockoutJS, Kendo MVVM 和 Knockback.js,而这些框架的社区都非常的活跃。

什么是MVVM

  • Model

作为MV*家族中的一员,MVVM中的M代表着Model。Model代表我们整个webapp所需要的数据模型,一个典型的例子就是用户信息Model,它应该含有(姓名,年龄等属性)。Model含有大量信息,但它并不具有任何行为逻辑,它只是数据,因而它不会影响浏览器如何展示数据。

  • View

View这个词出现频率最多的地方应该是MVC。在MVC设计中,View是唯一与用户交互的地方,或者说它是Model变化后的直观反映。在MVVM中,View被认为是主动的而非被动的。

一个被动的View时只它只能任由“他人”(Controller)摆布,自己却不能改变任何东西,如利用Jquery操作DOM。而MVVM中View是具有主动性的,因为它包括了一些数据绑定,事件,和行为,这些都会直接影响Model和ViewModel的。它不但负责保持View自己身的行为(展示),而还会将自身的变化同步到ViewModel中。

  • ViewModel

ViewModel可以被看作是MVC中的Controller,它主要负责数转换(用一定的业务逻辑),它负责将Model的变化反应到View上,而当View自身有变化时也会同步Model进行改变。

你可以把ViewModel看作一个藏在View后面的好帮手,它把View需要的数据暴露给它,并且富于View一定的行为能力。

说了这么多,先看一个knockoutjs的Demo:

html

    <!-- This is a *view* - HTML markup that defines the appearance of your UI -->

    <p>First name: <strong data-bind="text: firstName"></strong></p>
    <p>Last name: <strong data-bind="text: lastName"></strong></p>

javascript

    // This is a simple *viewmodel* - JavaScript that defines the data and behavior of your UI
    function AppViewModel() {
        this.firstName = "Bert";
        this.lastName = "Bertington";
    }

    // Activates knockout.js
    ko.applyBindings(new AppViewModel());

页面效果:

First name: Bert Last name: Bertington

ViewModel在View上绑定了text指令,告诉对应的tag可以利用ViewModel中的数据渲染DOM。这只是ViewModel对View的单项绑定,双向绑定需要observable对象,后续会有解释。

优点

  • 1.UI与逻辑的分离。
  • 2.写unit测试比较方便,毕竟测ViewModel要比测个种Event方便多了。

缺点

  • 1.如果你在Bindings里写了自定义的方法,而这个方法恰好需要调试时可能有些不便。
  • 2.对于交互很少的webapp,MVVM略显沉重
  • 3.对于大型webapp,所有逻辑和数据都在ViewModel里,ViewModel会越来越复杂。

其实MVVM的缺点还有很多,但都是一些在特定场景下的特定问题,而它的优点个人觉得就是上面的两大方面,尽管它也有很多不足和缺陷,但是当你的webapp属于中小型,并且有很复杂的交互时,如果你还在用类似于Jquery去操作DOM,那我还是劝你赶紧换框架吧。

基于一段时间使用MVVM的经验,个人觉得在特定场景下它确实很优秀,所以我决心自己尝试着去研究一下MVVM的实现原理,我将会以knockoutjs为基础,打造一套和它的接口相同的MVVM框架(部分主要接口),不求做的多优秀,只想动手实现一下,我将会在后续的博客中介绍如果实现MVVM中的模版引擎和数据绑定(单项,双向)。