網絡上有很多類似的討論。比如
廖雪峰:MVVM
司徒正美: 各自用一句話來概括MVC、MVP、MVVM的差異特點
。。。
但是說的往往比較概念化、空泛,初學者很難理解。本篇用最簡單的例子講解這三者,看完本篇,你就不會再糾結這個問題了
本文例子主要從MV*框架出發,實際上這些模式可以用到顆粒更小的層面。
框架的起源與目的
1.框架是一個可復用的設計構件
框架就是為大規模復用而生,為大型項目而生。小型項目由於不需要大規模復用,可不需要框架。
表現為組件的復用、項目的移植都應該非常容易。
2.框架規定了一種固定的、結構化的方式進行代碼的組織。
框架的目標是進行有效的知識積累。為此,相關的技術當以固定的格式,以代碼、文檔、模型等方式固化下來。
表現為:框架規定了代碼的結構層次(“高內聚、低耦合”),以及各個層次之間的關系;交互以及控制流程。
這塊可能有點抽象,簡單理解:框架就是規定了結構分層,每一層是干什么用的。然后你按照框架規定的范式進行編程,框架幫你處理層與層之間的交互與控制。
MVC
Model-View-Controller
view層:用戶界面
controller層:業務邏輯、路由
model層:數據結構、數據存儲
以jsp作為頁面模板開發為例,其他asp/php等類似(為了方便,下面用V表示View,C表示controller, M表示Model。后面的例子同理)
view層:
jsp頁面模板是屬於這一層。
controller層:
響應jsp頁面的用戶操作並處理的Servlet。servlet控制改變Model層的數據。所以數據流程是C到M。
Servlet處理中路由功能會告訴服務器處理完成之后下一個展示的該是哪個jsp頁面。這塊僅僅是路由功能,servlet和“下一個展示的jsp頁面”沒有交互和數據的傳遞。所以V到C是單項的。
model層:
這一層主要定義基本數據結構和數據存儲。jsp頁面模板中,需要從M層獲取最新的數據組裝頁面,所以是M到V。
到此,對MVC框架就應該比較了解了。
MVC模式有多種變種,數據流的方向可能也不同。但是有兩個特點:三層隔離的數據模型、V和M層有數據交互。
MVP
Model-View-Presenter
view層:用戶界面
presenter層:業務邏輯、路由
model層:數據結構、數據存儲
為什么要MVP?從MVC的流程可以看到,V層數據是從M層獲取的。最上層和最底層直接交互,意味着什么?
在前后端沒有分工的時候沒有問題,V層開發者就是M層開發者,所以對M的數據結構了如指掌,要什么數據知道怎么去獲取。
但是V層越來越復雜、ajax做局部頁面渲染的出現以及前后端分工導致V層開發者更專注於交互設計,已經沒有精力去掌控M層的細節了。
這時,V層希望的是:有特定的接口返回約定好的數據。這些數據和M層的數據可能有很大的不同,應該有一個中間層來提供。之前的MVC的C層來干這件事比較合適。所以變成了P層,P層除了干C層的事,還多了為V層提供各種各樣功能接口。
現在V層和M層完全分來了。前后端的開發人員都能將精力集中在該干的事上。
MVVM
Model-View-ViewModel
view層:用戶界面、響應viewModel變化處理
viewModel層:界面業務邏輯、路由
model層:后台業務邏輯、數據結構、數據存儲
前端的復雜度指數級的上升。比如你可以看到類似Scratch這樣純前端的圖形化編程系統,代碼量以千萬行為單位,是有必要為這樣龐大的系統做框架設計的。MVVM就是為此而生。
在MVVM的視界里,M層不是關鍵,你可以把整個后台都看成M層。
V層是用戶界面,並且感知到VM層數據的變化V層會跟隨變化(你不需要知道V層怎么感知到VM層數據變化的,這就是框架幫你做的事),可以稱之為主動視圖(這就是MVVM和MVP的區別,MVC/MVP的視圖都是被動視圖)。
VM層才是重點。在框架中,VM層定義了V層需要的直接數據結構(所以才帶Model字樣),V層的事件以及數據變化都會經過框架,流入VM層進行處理,進行業務邏輯的處理、數據的變更以及和M層的交互。
Angular、Vue、React都是類似的。簡單理解:前端開發中模板即V層,后台屬於M層,按照框架的范式開發的部分就是VM層。
細心的你可能看到了一點:VM層居然包含了“路由”功能。在MVC、MVP框架中,路由都是屬於服務器功能,單頁面的興起,讓路由納入了前端的功能圈,MVVM框架非常適合單頁面
當然這些MVVM框架都支持在服務端渲染,一旦用在服務端渲染,框架就失去了V層的響應式,直接就編程練一個模板引擎了,不能再稱之位MVVM框架了。
到此,你應該對三種模式有了足夠的認識了。
這三種模式從小的層面來說,可以構建一些簡單的數據交互結構,大的層面可以用來構建框架。
從框架的層面和歷史發展來看:MVC和MVP都主要為簡化服務端渲染視圖而設計的,MVVM則是為了簡化前端頁面開發而設計的。
從模式的方面來看:MVC、MVP和MVVM的思想可以用在更小的代碼顆粒中。
上面的示例以Web頁面來描述的。同理推廣到其他視圖交互應用都是可以的。
說一個題外話,框架和庫的區別就比較明顯了。庫只是提供拓展的功能,而框架則是規定了代碼分層,並讓你必須按它的結構進行代碼編寫。這就是Jquery不是框架的原因。