文章出處

返回目錄

百度百科的定義:

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。

 

返回目錄


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()