百度百科的定義:
MVP 是從經典的模式MVC演變而來,它們的基本思想有相通的地方:Controller/Presenter負責邏輯的處理,Model提供數據,View負 責顯示。作為一種新的模式,MVP與MVC有著一個重大的區別:在MVP中View并不直接使用Model,它們之間的通信是通過Presenter (MVC中的Controller)來進行的,所有的交互都發生在Presenter內部,而在MVC中View會從直接Model中讀取數據而不是通過 Controller。
在MVC里,View是可以直接訪問Model的!從而,View里會包含Model信息,不可避免的還要包括一些 業務邏輯。 在MVC模型里,更關注的Model的不變,而同時有多個對Model的不同顯示,及View。所以,在MVC模型里,Model不依賴于View,但是 View是依賴于Model的。不僅如此,因為有一些業務邏輯在View里實現了,導致要更改View也是比較困難的,至少那些業務邏輯是無法重用的。
MVVM在概念上是真正將頁面與數據邏輯分離的模式,在開發方式上,它是真正將前臺代碼開發者(JS+HTML)與后臺代碼開發者分離的模式(asp,asp.net,php,jsp)。
MVP與傳統MVC的區別,但目前我們提倡的MVC已經走向MVP了
在MVP里,Presenter完全把Model和View進行了分離,主要的程序邏輯在Presenter里實現。而且,Presenter與具體的 View是沒有直接關聯的,而是通過定義好的接口進行交互,從而使得在變更View時候可以保持Presenter的不變,即重用!
不僅如此,我們還可以編寫測試用的View,模擬用戶的各種操作,從而實現對Presenter的測試--而不需要使用自動化的測試工具。 我們甚至可以在Model和View都沒有完成時候,就可以通過編寫Mock Object(即實現了Model和View的接口,但沒有具體的內容的)來測試Presenter的邏輯。
在MVP里,應用程序的邏輯主要在Presenter來實現,其中的View是很薄的一層。因此就有人提出了Presenter First的設計模式,就是根據User Story來首先設計和開發Presenter。在這個過程中,View是很簡單的,能夠把信息顯示清楚就可以了。在后面,根據需要再隨便更改View, 而對Presenter沒有任何的影響了。 如果要實現的UI比較復雜,而且相關的顯示邏輯還跟Model有關系,就可以在View和Presenter之間放置一個Adapter。由這個 Adapter來訪問Model和View,避免兩者之間的關聯。而同時,因為Adapter實現了View的接口,從而可以保證與Presenter之 間接口的不變。這樣就可以保證View和Presenter之間接口的簡潔,又不失去UI的靈活性。 在MVP模式里,View只應該有簡單的Set/Get的方法,用戶輸入和設置界面顯示的內容,除此就不應該有更多的內容,絕不容許直接訪問 Model--這就是與MVC很大的不同之處。
目前我們提倡的MVC已經與MVP沒有太大區別,View依然是很薄的一層,不進行與Model的邏輯處理,只進行簡單的頁面顯示的邏輯處理。
MVVM是Model-View-ViewModel的簡寫。
微軟的WPF帶來了新的技術體驗,如Sliverlight、音頻、視頻、3D、動畫……,這導致了軟件UI 層更加細節化、可定制化。同時,在技術層面,WPF(原來winform那邊的)也帶來了 諸如Binding、Dependency Property、Routed Events、Command、DataTemplate、ControlTemplate等新特性。MVVM(Model-View- ViewModel)框架的由來便是MVP(Model-View-Presenter)模式與WPF結合的應用方式時發展演變過來的一種新型架構框架。 它立足于原有MVP框架并且把WPF的新特性揉合進去,以應對客戶日益復雜的需求變化。
MVC中引入MVVM的意義
前端工程師們與程序開發人員們實現了真正的分離,當然,為了減少重復代碼量,前端人員有必要了解一個數據庫結構。
前端進行MVVM的JS插件,knockoutjs
Knockoutjs可以靈活的實現數據的綁定工作,對于前臺開發人員來說,不需要關心后臺數據以何種方式產生,它們只需要關心數據的屬性簽名即可,對于程序開發人員來說,它們關心的是數據產生的接口,包括簡單的CURD操作接口,程序開發人員完成可以把這些邏輯寫在單獨的JS文件中,由HTML頁面指定引用,真實數據即可完成綁定工作。
使用knockoutjs來實現MVC中的MVVM模式
html代碼:
<table> <thead> <tr> <th>編號</th> <th>姓名</th> <th>電話</th> <th>操作</th> </tr> </thead> <tbody data-bind="template:{name:'list',foreach: lines}"> </tbody> <tfoot> <tr> <td colspan="4"> <button data-bind='click: addLine'>Add</button></td> </tr> </tfoot> </table> <script type="text/html" id="list"> <tr> <td><span data-bind="text:Id"></span></td> <td> <span data-bind="text: Name"></span> </td> <td> <span data-bind="text: PhoneNo"></span> </td> <td> <a href='#' data-bind='click: $parent.removeLine'>Remove</a> </td> </tr> </script>
controller層C#代碼得到數據:
public IEnumerable<Contact> Get() { Contact[] contacts = new Contact[] { new Contact{Id=1, Name="張三", PhoneNo="123", EmailAddress="zhangsan@gmail.com"}, new Contact{Id=2, Name="李四", PhoneNo="456", EmailAddress="lisi@gmail.com"}, new Contact{Id=3, Name="王五", PhoneNo="789", EmailAddress="wangwu@gmail.com"}, }; return contacts; }
knockoutjs代碼用來綁定數據和實現頁面的交互
<script type="text/javascript"> var CartLine = function () { var self = this; self.Id = ko.observable(); self.Name = ko.observable(); self.PhoneNo = ko.observable(135); self.EmailAddress = ko.observable("@"); }; $.getJSON("http://localhost:2166/api/values/", function (data) { var Cart = function () { // Stores an array of lines, and from these, can work out the grandTotal var self = this; //self.lines = ko.observableArray([new CartLine()]); self.lines = ko.observableArray(data); // Operations self.addLine = function () { self.lines.push(new CartLine()) }; self.removeLine = function (line) { self.lines.remove(line) }; } ko.applyBindings(new Cart()); });
OK,到了這里,一個MVVM風格的實例已經講解完了,下回我們將逐步來學習knockoutjs。
文章列表