1. 首页
  2. >
  3. 前端开发
  4. >
  5. Vue

Vue之MVVM模型和MVC模型

MVVM

MVVM简介

核心思想:

分而治之(不同业务代码放到不同业务模块当中,通过特定逻辑组织到一块)

MVVM其实是 M、V、VM,即 Model-View-ViewModel 的缩写。它是一种基于前端开发的架构模式,其核心是提供对View 和 ViewModel 的双向数据绑定,这使得 ViewModel 的状态改变可以自动传递给 View,即所谓的数据双向绑定。

Vue.js 是一个提供了 MVVM 风格的双向数据绑定的 Javascript 库,专注于View 层。它的核心是 MVVM 中的 VM,也就是 ViewModel。 ViewModel负责连接 View 和 Model,保证视图和数据的一致性,这种轻量级的架构让前端开发更加高效、便捷。


啥是Model、View、ViewModel?


Model

可以把Model称为数据层,因为它仅仅关注数据本身,不关心任何行为(格式化数据由View的负责),这里可以把它理解为一个类似json的数据对象,主要存的是页面中的数据。

//可以把它理解为一个类似json的数据对象 var data = {     val: 0 };

Model层代表的是模型、数据,可以在Model层中定义数据修改和操作的业务逻辑。


View

指的是所看到的页面,和MVC/MVP不同的是,MVVM中的View通过使用模板语法来声明式地将数据渲染进DOM,当ViewModel对Model进行更新的时候,会通过数据绑定更新到View。

例如:

div id="myapp">     <div>         <span>{{ val }}rmb</span>     </div>     <div>         <button v-on:click="sub(1)">-</button>         <button v-on:click="add(1)">+</button>     </div> </div>

View层代表的是视图、模版,负责将数据模型转化为UI展现出来。


ViewModel

MVVM模式的核心,它是连接view和model的桥梁。它有两个方向:

  1. 将Model转化成View,即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定
  2. 将View转化成Model,即将所看到的页面转化成后端的数据。实现的方式是:DOM 事件监听

这两个方向都实现的,我们称之为数据的双向绑定

例如:

new vue({     el: '#myapp',     data: data,     methods: {         add(v) {             if(this.val < 100) {                 this.val += v;             }         },         sub(v) {             if(this.val > 0) {                 this.val -= v;             }         }     } });

MVVM模型

Vue之MVVM模型和MVC模型

在MVVM的架构下,View层和Model层并没有直接联系,而是通过ViewModel层进行交互。

ViewModel通常要实现一个observer观察者,当数据发生变化,ViewModel能够监听到数据的这种变化,然后通知到对应的视图做自动更新,而当用户操作视图,ViewModel也能监听到视图的变化,然后通知数据做改动,这实际上就实现了数据的双向绑定

ViewModel层通过双向数据绑定将View层和Model层连接了起来,使得View层和Model层的同步工作完全是自动的。因此开发者只需关注业务逻辑,无需手动操作DOM,复杂的数据状态维护交给MVVM统一来管理。


Vue.js中MVVM的体现

Vue.js的实现方式,对数据(Model)进行"劫持",当数据变动时,数据会触发劫持时绑定的方法,对视图进行更新

vue中MVVM的体现:

Vue之MVVM模型和MVC模型

实例分析:

Vue之MVVM模型和MVC模型

由例子可知ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干预。


Vue.js关于双向数据绑定的一些实现细节

下面我又简单地了解了一下Vue.js关于双向数据绑定的一些实现细节;主要参考了下面这篇文章,很有研究价值,有意向者可以去看一下:深入MVVM模型带你理解Vue.js的双向绑定

vue是采用Object.defineProperty的getter和setter,并结合观察者模式来实现数据绑定的。当把一个普通的javascript对象传给Vue实例来作为它的data选项时,Vue将遍历它的属性,用Object.defineProperty将它们转为getter/setter。用户看不到getter/setter,但是在内部它们让Vue追踪依赖。在属性被访问和修改时通知变化。

vue双向绑定图示:

Vue之MVVM模型和MVC模型

  • Observer数据监听器,能够对数据对象的所有属性进行监听,如有变动可拿到最新的值并通知订阅者,内部采用的Obiect.defineProperty的getter和setter来实现。
  • complie指令解析器,它的作用对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定Observer和Complie的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应的回调函数
  • Watcher订阅者,作为连接Observer和Complie的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数。
  • Dep消息订阅器,内部维护了一个数组,用来收集订阅者(watcher),数据变动触发notify函数,再调用订阅者的update方法。

以上过程可总结为:

Observer相当于Model层观察vue实例中的data数据,当数据发生变化时,通知Watcher订阅者。

Compile指令解析器位于View层,初始化View的视图,将数据变化与更新函数绑定,传给Watcher订阅者。

Watcher是整个模型的核心,对应ViewModel层,连接Observer和Compile。所有的Watchers存于Dep订阅器中,Watcher将Observer监听到的数据变化对应相应的回调函数,处理数据,反馈给View层更新界面视图。


MVC

MVC简介

MVC 模式代表 Model-View-Controller(模型-视图-控制器) 模式。这种模式用于应用程序的分层开发。


MVC的Model、View、Controller


Model(模型)

Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。

Model定义了这个模块的数据模型。在代码中体现为数据管理者,Model负责对数据进行获取及存放

Model既是数据管理者,也由它来负责获取数据,数据不可能凭空生成的,要么是从服务器上面获取到的数据,要么是本地数据库中的数据,也有可能是用户在UI上填写的表单即将上传到服务器上面存放,所以需要有数据来源。既然Model是数据管理者,则自然由它来负责获取数据。

MVC允许在不改变视图的情况下改变视图对用户输入的响应方式,用户对View的操作交给了Controller处理,在Controller中响应View的事件调用Model的接口对数据进行操作,一旦Model发生变化便通知相关视图进行更新。

这里我们把需要用到的数值变量封装在Model中,并定义了add、sub、getVal三种操作数值方法

var myapp = {}; // 创建这个应用对象  myapp.Model = function() {     var val = 0;      this.add = function(v) {         if (val < 100) val += v;     };      this.sub = function(v) {         if (val > 0) val -= v;     };      this.getVal = function() {         return val;     };      /* 观察者模式 */     var self = this,          views = [];      this.register = function(view) {         views.push(view);     };      this.notify = function() {         for(var i = 0; i < views.length; i++) {             views[i].render(self);         }     }; }

Model和View之间使用了观察者模式,View事先在此Model上注册,进而观察Model,以便更新在Model上发生改变的数据。


View(视图)

View(视图)是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。

View,视图,简单来说,就是我们在界面上看见的一切

view和controller之间使用了策略模式,这里View引入了Controller的实例来实现特定的响应策略,比如这个栗子中按钮的 click 事件:

myapp.View = function(controller) {     var $num = $('#num'),         $incBtn = $('#increase'),         $decBtn = $('#decrease');      this.render = function(model) {         $num.text(model.getVal() + 'rmb');     };      /*  绑定事件  */     $incBtn.click(controller.increase);     $decBtn.click(controller.decrease); }

如果要实现不同的响应的策略只要用不同的Controller实例替换即可。


Controller(控制器)

Controller(控制器)是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据

Controller是MVC中的数据和视图的协调者,也就是在Controller里面把Model的数据赋值给View来显示(或者是View接收用户输入的数据然后由Controller把这些数据传给Model来保存到本地或者上传到服务器)

myapp.Controller = function() {     var model = null,         view = null;      this.init = function() {         /* 初始化Model和View */         model = new myapp.Model();         view = new myapp.View(this);          /* View向Model注册,当Model更新就会去通知View啦 */         model.register(view);         model.notify();     };      /* 让Model更新数值并通知View更新视图 */     this.increase = function() {         model.add(1);         model.notify();     };      this.decrease = function() {         model.sub(1);         model.notify();     }; };

这里我们实例化View并向对应的Model实例注册,当Model发生变化时就去通知View做更新,这里用到了观察者模式。

当我们执行应用的时候,使用Controller做初始化:

(function() {     var controller = new myapp.Controller();     controller.init(); })();

MVC中的通讯

各部分之间的通信方式如下,所有通讯都是单向的 。

  1. View 传送指令到 Controller
  2. Controller 完成业务逻辑后,要求 Model 改变状态
  3. Model 将新的数据发送到 View,用户得到反馈

Vue之MVVM模型和MVC模型

接受用户指令时,MVC 可以分成两种方式:

一种是通过 View 接受指令,传递给 Controller:

Vue之MVVM模型和MVC模型

另一种是直接通过controller接受指令:

Vue之MVVM模型和MVC模型

MVC模式的业务逻辑主要集中在Controller,而前端的View其实已经具备了独立处理用户事件的能力,当每个事件都流经Controller时,这层会变得十分臃肿。而且MVC中View和Controller一般是一一对应的,捆绑起来表示一个组件,视图与控制器间的过于紧密的连接让Controller的复用性成了问题。