MVC,MVP和MVVM都是常見的軟件架構設計模式,它經過分離關注點來改進代碼的組織方式。前端
它們相同的部分是MV(Model-View),而不一樣部分則是C(Controller)、P(Presenter)、VM(View-Model)。json
MVC設計模式
Model層用於封裝和應用程序的業務邏輯相關的數據以及對數據的處理方法。前端框架
做爲視圖層,主要負責數據的展現。架構
控制器是模型和視圖之間的紐帶,MVC將響應機制封裝在controller對象中,當用戶和你的應用產生交互時,控制器中的事件觸發器就開始工做了。app
<div id="num"></div> <button id="decrease">-</button> <button id="increase">+</button> <script> //建立應用對象 var myapp = {} //Model層 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; var views = []; this.register = function (view) { views.push(view) } this.notify = function () { for (var i = 0; i < views.length; i++) { views[i].render(self) } } } //View層 myapp.View = function (controller) { //視圖元素 var $num = document.getElementById('num') var $inBtn = document.getElementById('increase') var $deBtn = document.getElementById('decrease') //渲染數據 this.render = function (model) { $num.innerHTML = model.getVal() } /* 綁定事件 */ $inBtn.onclick = function () { controller.increase() } $deBtn.onclick = function () { controller.decrease() } } //Controller層 myapp.Controller = function () { var model = null; var 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() } } //運行,使用Controller作初始化 !(function () { var controller = new myapp.Controller() controller.init() })(); </script>
MVC模式的業務邏輯主要集中在Controller層,而View層其實已經具有了獨立處理用戶事件的能力,當每一個事件都流經Controller層時,這層會變得十分臃腫。框架
並且,View層和Controller層通常是一一對應的,捆綁起來表示一個組件,視圖與控制器間的過於緊密的鏈接讓Controller層的複用性成了問題。this
MVPspa
是MVC模式的改良。和MVC的相同之處是:Controller和Presenter負責業務邏輯,Model管理數據,View負責顯示。架構設計
在MVC裏,View是能夠直接訪問Model的,但MVP中的View不能直接使用Model,而是經過爲Presenter提供接口,讓Presenter去更新Model,再經過觀察者模式更新View。
與MVC相比,MVP模式經過解耦View和Model,徹底分離視圖和模型使職責劃分更加清晰;因爲View不依賴Model,能夠將View抽離出來作成組件,它只須要提供一系列接口提供給上層操做。
依然是主要與業務相關的數據和對應處理的數據的方法
定義了Presenter和View之間的接口,用戶對View的操做都轉移到了Presenter。
Presenter做爲View和Model之間的「中間人」,除了基本的業務邏輯外,還有大量代碼須要對從View到Model和從Model到View的數據進行「手動同步」,這樣Presenter顯得很重,維護起來會比較困難。並且因爲沒有數據綁定,若是Presenter對視圖渲染的需求增多,它不得不過多關注特定的視圖,一旦視圖需求發生改變,Presenter也須要改動。
<div id="num"></div> <button id="decrease">-</button> <button id="increase">+</button> <script> //建立應用對象 var myapp = {} //Model層 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; } } //View層 myapp.View = function () { //視圖元素 var $num = document.getElementById('num') var $inBtn = document.getElementById('increase') var $deBtn = document.getElementById('decrease') //渲染數據 this.render = function (model) { $num.innerHTML = model.getVal() } /* 綁定事件 爆露setter接口讓Presenter調用*/ this.init = function(){ //建立presenter var presenter = new myapp.Presenter(this); $inBtn.onclick = function () { presenter.increase() } $deBtn.onclick = function () { presenter.decrease() } } } //Controller層 myapp.Presenter = function (view) { //初始化Model 和 View var _model = new myapp.Model(); var _view = view; //初始化視圖更新 _view.render(_model) /* 讓Model更新數據並通知View更新視圖 */ this.increase = function () { _model.add(1) _view.render(_model) } this.decrease = function () { _model.sub(1) _view.render(_model) } } //運行,使用Controller作初始化 !(function () { var view = new myapp.View() view.init() })(); </script>
MVVM
MVVM把View和Model的同步邏輯自動化了。之前Presenter負責的View和Model同步再也不手動地進行操做,而是交給框架所提供的數據綁定功能進行負責,只須要告訴它View顯示的數據對應的是Model哪一部分便可。以Vue舉例。
在MVVM中,咱們能夠把Model稱爲數據層,由於它僅僅關注數據自己,不關心任何行爲(格式化數據由View的負責),這裏能夠把它理解爲一個相似json的數據對象。
var data = { val: 0 };
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>
ViewModel大體上就是MVC的Controller和MVP的Presenter了,也是整個模式的重點,業務邏輯也主要集中在這裏,其中的一大核心就是數據綁定,與MVP不一樣的是,沒有了View爲Presente提供的接口,以前由Presenter負責的View和Model之間的數據同步交給了ViewModel中的數據綁定進行處理,當Model發生變化,ViewModel就會自動更新;ViewModel變化,Model也會更新。
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框架中,實現雙向數據綁定的技術有所不一樣。目前一些主流的前端框架實現數據綁定的方式大體有如下幾種: