最近想總結一下前端中的MV*(MVC、MVP、MVVM)模式。前端
可是,鑑於本身的理解仍是比較侷限,我想在此轉Livoras的一篇博客。git
本文對這篇博客的觀點比較贊同,而且引用了該文章的圖片。你們能夠沒必要展開個人文章,直接讀這一篇大做。github
原文連接:界面之下:還原真實的MV*模式。web
注:本文有圖,可是因爲網絡緣由,圖片未能上傳,後續補上。?設計模式
<!--more-->前端框架
簡而言之,我認爲MV*就是實現了領域模型數據和UI層的解耦。網絡
可是MVC、MVP、MVVM對其解耦的思路的不一樣。從歷史的角度來看,MVC、MVP和MVVM是一種進化的關係。可是鑑於項目的規模以及模式實現的方式不一樣,不一樣的MV*模式各有其優勢和缺點,難分孰好孰壞。架構
可是業界愈來愈認爲:MVVM是前端領域最好的MV*模式。框架
下面我就分別談一下這三種模式。翻譯
MVC模式的應用程序,除了有UI層(View)和領域模型(Model)以外,多加了一層Controller。他們之間的關係是這樣的:
用戶對View的輸入等操做並不會在View的相關模塊中處理邏輯,而是由Controller層得到這些操做(所謂的Pass Call),並由Controller層對這些操做中的數據通過應用邏輯的操做,而後在調用Model層的接口,將數據交給Model層。Model層執行與業務邏輯相關的操做,並更新數據。Model和View經過觀察者模式聯繫在一塊兒,即View是Model的觀察者,當Model數據變更以後,通知View層進行數據更新。
咱們看到MVC是一個單向的三角關係。
總的來講:
Model主要是與業務數據有關。
View是應用程序數據的可視化表示。
Controller管理應用程序中Model和View之間的邏輯和協調。
View瞭解Controller,Controller瞭解Model,而View可以直接訪問Model。
MVP比起MVC模式,它的特色很明顯。MVP中M和V之間的依賴關係被消除了。
在MVC中,M和V之間經過觀察者模式依賴。這種依賴關係在MVP中被轉移到M和P層中。這樣一來P層必須經過必定的機制通知V層進行數據的更新。因此MVP模式中V層中提供了供P層調用的接口。P層做爲觀察者得到數據變化是,將調用V層的接口將變化反映到V層中。
總的來講,MVP中:
Model層依然是主要與業務數據有關。
View依然是應用程序的可視化表示,可是在MVP中它對領域數據(Model層)徹底無知,比起MVC中View層更輕了。
Presenter層比較重,它不只調用Model的接口,也調用View的接口。並且須要做爲觀察者得到Model的數據更新。
最後來看下MVVM模式:
MVVM模式中,M層數據的變化不是經過觀察者模式通知到V層的(即沒有M和V的依賴),也不是經過VM層調用V層的接口將數據傳遞給V層的(這意味着用戶代碼不須要手動更新V層)。而是經過在VM層實現一個特殊的binder,將數據從M層直接綁定到V層。這樣ViewModel層瞭解Model層,View層瞭解ViewModel層。
ViewModel充當了一個數據轉換器的做用。它將Model信息轉換爲View信息,還將命令從View傳遞到Model。在這裏,View能夠訪問ViewModel,ViewModel能夠訪問Model。
我理解的ViewModel是:
ViewModel爲View提供了一個訪問Model的橋樑,可是View不是直接訪問Model層。ViewModel爲View提供了Model的特定於View的子集,能夠包含狀態和邏輯信息,並且無需向View暴露整個Model。
View和ViewModel經過數據綁定和事件能夠進行通訊,由於ViewModel能夠訪問Model層,因此ViewModel爲了數據綁定要暴露Model中的部分屬性。
關於業務邏輯,不少前端框架都單獨作了一個與MVVM無關的Service層,將業務邏輯放到Service層中,由ViewModel調用。即:View => ViewModel => Service這樣一個流向。
對於雙向綁定《界面之下》是這麼描述的:
雙向數據綁定。能夠簡單而不恰當地理解爲一個模版引擎,可是會根據數據變動實時渲染。
其實我不是很肯定這樣理解對不對。
不過雙向綁定帶來了一個缺點,那就是數據綁定的聲明是指令式地寫在View的模版當中的,這些內容是沒辦法去打斷點debug的。
MVC、MVVM等高大上的詞彙,從我開始接觸web開發的時候就不絕於耳。開始使用ExtJS4.2的時候,「大神」告訴我這是一個實現了MVC模式的框架。而後還很耐心的告訴我:MVC有三層,它們分別放在不一樣的文件夾下。這個XX.view.js實現了View層,這個XX.Model.js實現了Model層,這個XX.controller.js實現了Controller層。
後來,我開始對Vue.js感興趣。我告訴「大神」說這是個MVVM模式的框架。他也很興奮,指着個人代碼興沖沖的問我:你寫這些個東西,哪一個是Model呢?我也被問蒙了,對啊,Model在哪呢?
直到我再也不跟着「大神」幹活以後,我才發現,那些話都是狗屁。
(我沒有說誰壞話的意思。也多是我對他的話有誤解,因此才形成了我如今的困惑。)
誠然,框架幫咱們實現了MV*模式,不表明咱們寫的代碼也是按照MV*模式組織的。由於咱們使用了框架,自己就意味着咱們認同它的架構和模式,而後調用框架的API,來實現業務層代碼。所以即便用戶代碼中出現相似vm
,view
等等的命名,也不表明這段代碼就是MV*中某一層的實現,而更像是對某一層的實現的一個擴展。並且不一樣的模式下的用戶代碼量級確實有時會有顯著差距。
再總結如下三點:
MV*模式的框架 + 用戶代碼 約== MV*模式的軟件
MV*模式的框架,是MV*模式的一個實現。
模式提供的通用解決方案,其記錄方式並不與某個特定問題掛鉤(《JavaScript設計模式》, O'RELLY出版)。
最後再吐槽一下:《JavaScript設計模式》這本書,翻譯的真心不太好,我真的讀不通順。
一點微小的看法,多多指正。
完。