由浅入深讲述MVVM

相信首次据说MVVM的人,心里都是充满疑惑的!这是个嘛???能干吗???javascript

MVVM是Model-View-ViewModel的简写。它本质上就是MVC (Model-View- Controller)的改进版。即模型-视图-视图模型。【模型】指的是后端传递的数据。【视图】指的是所看到的页面。【视图模型】mvvm模式的核心,它是链接view和model的桥梁。它有两个方向:一是将【模型】转化成【视图】,即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。二是将【视图】转化成【模型】,即将所看到的页面转化成后端的数据。实现的方式是:DOM 事件监听。这两个方向都实现的,咱们称之为数据的双向绑定。html

总结:在MVVM的框架下视图和模型是不能直接通讯的。它们经过ViewModel来通讯,ViewModel一般要实现一个observer观察者,当数据发生变化,ViewModel可以监听到数据的这种变化,而后通知到对应的视图作自动更新,而当用户操做视图,ViewModel也能监听到视图的变化,而后通知数据作改动,这实际上就实现了数据的双向绑定。而且MVVM中的View 和 ViewModel能够互相通讯。前端

 

 

 

MVVM 就是将其中的View 的状态和行为抽象化,让咱们将视图 UI 和业务逻辑分开。固然这些事 ViewModel 已经帮咱们作了,它能够取出 Model 的数据同时帮忙处理 View 中因为须要展现内容而涉及的业务逻辑。MVVM(Model-View-ViewModel)框架的由来即是MVP(Model-View-Presenter)模式与WPF结合的应用方式时发展演变过来的一种新型架构框架。它立足于原有MVP框架而且把WPF的新特性糅合进去,以应对客户日益复杂的需求变化。vue

 

对于第一次接触的人看了上面的解释以后,可能仍是似懂非懂,那么让咱们从基础的看起吧,刚才咱们说过MVVM是它本质上就是MVC的改进版。那么MVC又是什么?它为何须要改进呢?java

MVC全名是Model View Controller,MVC是Model-View- Controller的简写。即模型-视图-控制器。M和V指的意思和MVVM中的M和V意思同样。C即Controller指的是页面业务逻辑。使用MVC的目的就是将M和V的代码分离。‘MVC是单向通讯。也就是View跟Model,必须经过Controller来承上启下。MVC和MVVM的区别并非VM彻底取代了C,ViewModel存在目的在于抽离Controller中展现的业务逻辑,而不是替代Controller,其它视图操做业务等仍是应该放在Controller中实现。也就是说MVVM实现的是业务逻辑组件的重用。因为mvc出现的时间比较早,前端并不那么成熟,不少业务逻辑也是在后端实现,因此前端并无真正意义上的MVC模式。而咱们今天再次提起MVC,是由于大前端的来到,出现了MVVM模式的框架,咱们须要了解一下MVVM这种设计模式是如何一步步演变过来的。 react

为何会有MVVM框架?jquery

在过去的10年中,咱们已经把不少传统的服务端代码放到了浏览器中,这样就产生了成千上万行的javascript代码,它们链接了各式各样的HTML 和CSS文件,但缺少正规的组织形式,这也就是为何愈来愈多的开发者使用javascript框架。好比:angular、react、vue。浏览器的兼容性问题已经再也不是前端的阻碍。前端的项目愈来愈大,项目的可维护性和扩展性、安全性等成了主要问题。当年为了解决浏览器兼容性问题,出现了不少类库,其中最典型的就是jquery。可是这类库没有实现对业务逻辑的分红,因此维护性和扩展性极差。综上两方面缘由,才有了MVVM模式一类框架的出现。好比vue,经过数据的双向绑定,极大了提升了开发效率。后端

(PS: 这里的MVP, MVVM甚至MXXX都只是MVC的变体而已,至于将重点放在C点仍是V点(没人会但愿放到M点吧?!)就天然引出了若干种所谓的模式,其实模式只有一种,你称为P也好VM也好,它都只是C的实例而已。老是设法弄出一些所谓的Business Word的家伙们,是前端开发最大的敌人!)设计模式

 又通过上面对MVC和MVVM的介绍,你们应该对他们应该有比较清楚的认识了吧。浏览器

 

在你们理解MVVM的概念以后,为了让你们能更深刻的理解MVVM,以便之后更好的运用,咱们再说一些细节性的东西吧。

 

 

1. 双向绑定

号称是最难理解的地方,

 

 

标准的数据驱动开发,应该如上图所示,在一个View的生命周期内,一个ViewModule会管理一个DomainObject(业务模型),一个DO可能包括多个Module数据模型,一个Module可能来自多个数据源,而不是想不少所谓的MVVM框架那样强迫一个M来一个数据源

按照上图标准分层方式来划分的好处,在于,逻辑清晰,Module层粒度够细,能够被屡次复用

DO层与VM层View层属于一一对应关系,方便对数据作增删改查的同步

每一层应该是独立的,非必定要使用MVVM框架的紧耦合,能够用本身使用不一样的js插件或者模块实现MVVM

咱们抛弃框架,单纯的看数据,其实咱们要解决的问题很简单

a) 当DO对象属性放生变化时候,通知View更新

b) 当View上表单值放生变化时,通知DO更新,并异步通知队列同步到数据源

先来看问题a,这个最简单,DO是一个基本的Javascript Object,咱们在View上的模板显示是这个Object.property,

改变一个Object对象的方式无非几种,一种是

a) 显示Object.property = ‘你好’

b) xxxx.methodName(Object, ‘property’,  ‘你好’)

c) xxxx.merge(Object, {‘property’:  ‘你好’})

若是是a的状况,ES5+,能够经过设置Object.defefineProperty(‘property’,{set: functiono(){},get:function(){}}),来作赋值和取值的监控触发

对于IE8一下,由于js不支持运算符重载,因此暂时没有好的办法,因此若是只考虑移动端的话,直接defineProperty就所有搞定,若是是要考虑PC的话,就不建议开发者使用直接赋值的方式,参考java的开发模式,也是推荐OOP时候,使用set方式赋值,而不是直接=赋值。

固然了,若是你非要兼容IE8一下的话,用定时器作轮训,配合for in 反射,经过脏数据与原始备份对比的方法也是一种办法,不过这种办法在当前页面很是耗性能,因为IE8一下不支持多线程,HTML5 worker,若是将来flash 插件支持多线程的话,却是能够用js和flash插件作线程交互的方式作脏数据检测。

若是是b的状况,那就太简单了,在methodName里面触发对于该属性修改的回调便可,如何注册回调呢,首先咱们要实现一个相似Dom Event的自定义对象的Event模型,而后经过相似Dom Event的注册事件方式,注册观察者,订阅事件,当执行了methodName时候,发送消息,通知全部订阅者执行回调

若是是c的状况,相似b同样处理

这样一看,双向数据绑定的问题就很是简单的解决了。

咱们再来看另一个MVVM的问题,非简单数据模型,复合数据模型(DO的属性值不是一个string,而是一个Object,且这个Object可能还嵌套多层Obejct的时候)的处理办法,这个通常的MVVM框架直接不考虑,或者经过长字段名的方式绕过这个问题

这个问题是这样的,早在10几年前,java structs框架流行的时候就出现了,当一个表单,出现须要对两个Java Bean作update操做时候,一个bean是user,一个bean是成绩

对应的表单字段名,就是 user表.name,user表.id,score表.point,

在struct2里面,处理逻辑是把 “点”做为特殊符号,在作form序列化时候,非包含点的字段的值都是string,包含点的字段是一个Object,好比刚才的form序列化以后结果就是 { user: {id :’’ , name: ‘’}, score: {id: ‘’, point: ‘’}}

同理在MVVM实现时,也是同样,认为点是分割对象的关键字,这样咱们就能够实现把多个对象嵌套到View模板里面,实现复合Object的双向映射。

 

最后再给你们介绍几种经常使用的前端MVVM开发框架:Angular.js,react,vue。 (他们的区别我就不一一来讲来,详情可见 https://www.cnblogs.com/wdtzms/p/6557894.html。)
angular  谷歌
它的版本更新特别快,每次更新后,写法都会有不少变化。如今国内依然还有不少公司在使用angular.js 1.X的版本。
react  facebook
是一个单项数据流的针对view层的框架,主要是作视图渲染。代码写法相对简洁。
vue 我的
vue是一个mvvm的框架,是现阶段国内使用范围最广的一个,用这个框架通常比较轻松。纯中文文档,纯中文社区,纯中文交流,相关资源很好找。
 

关于MVVM就为你们介绍这么多,但愿对你有帮助。

走以前别忘了赞加关注哟!

 

相关文章
相关标签/搜索