淺談MVC/MVP/MVVM模式(概述)

本文來自我的博客這個想法不一定對系列,so,這個想法不一定對😉

一切皆爲數據(0,1),一切皆可量化

不管承不承認,頁面的展示都是數據的可視化。HTML 是數據,CSS 是數據,JS也是數據。只是這些數據的組合最終變成了我們想要的效果。

最爲直觀的是,我們在開發者工具 Console 控制檯中,輸入任何形式的數據並點擊 Enter 時,最終會在下方顯示出來(前提是輸入正確的數據類型和格式)。又或者,我們用某些參數從服務請求一個 JSON 文件,瀏覽器上就會展示文件內容。數據 => 視圖,就是這麼簡單直接。

引子

然而,實際上的情況遠遠比這複雜。爲了更好的視覺享受和用戶體驗,瀏覽器上的頁面效果越來越炫,交互邏輯也越來越複雜。我們拿到的第一手數據(或來自用戶,或來自服務)已經不能直接用來展示了,而是要經過相應的邏輯處理(在這裏我們稱第一手數據爲源數據,經過邏輯處理後的數據稱爲目標數據)。視圖上的數據就是目標數據的映射。

而處理後的數據又該如何展示呢?是基於 DOM 做操作,還是基於目標數據重新渲染呢?兩者都可,前者是以 jQuery 爲代表,後者則是以 Vue 等新框架爲主。舉個例子🌰,對於某個 DOM 元素的顯隱。

< !--jQuery -->
  <div id='jquery'></div>
$('#jquery').hide();

< !--Vue -->
  <div id='jquery' v-show={id[jquery]}></div>
data: {
  id: {
    jquery: fasle
  }
}

基於 DOM 操作, 如果我們需要對這個 DOM 隨時改變顯隱,就需要不斷操作 DOM 來更改樣式。 如果基於數據操作,我們只需要更改 jQuery 的值即可。

我們再回到剛纔的話題,對於複雜的交互頁面,數據 => 視圖 的關係已經不再像之前那麼純淨了。爲了應付複雜的場景,數據視圖 不再是狹義上的數據和視圖。數據包括了數據和數據相關的操作,視圖包括了視圖和對視圖相關的一些操作。

MV*模式

借用MV* 框架模式,這裏的 數據視圖 對應着 ModelView. 簡單點的頁面,Model - View 完全能夠應付過來。但是複雜的場景,ModelView 會分擔太多的邏輯而顯得臃腫,甚至可能包含了不在自己職責範圍內的邏輯。

此時我們就要藉助第三者來協調 ModelView 之間的關係。如何合作,其實也早有了相應的解決方案。比如 MVC、MVP、MVVM。因爲重點始終在於協調 ModelView,所以它們統稱爲 MV*

MVC&MVP.jpg

MVC (Model(模型)-View(視圖)-Controller(控制器)), MVP (Model(模型)-View(視圖)-Presenter(中介者)) 以及 MVVM (Model(模型)-View(視圖)-ViewModel(視圖模型)),是種模式也是種抽象的概念。

每一種模式在實踐中可能存在着不同的變體,但這不妨礙它們屬於同一個模式。每一種模式的不同變體都是爲了解決不同問題而產生的,所以它們沒有什麼優劣之分。

現在我們就把三種模式擬人化來闡述不同模式的運作方式。

由四節電池驅動的J-20模型:
J-20.jpg

MVC

公司:飛機模型製造商 => 生產的飛機模型可以自主塑形。

模式:MVC

飛機模型 V:由模型數據生產出的模型。職責有:由模型數據自主塑形、將收集用戶反饋並轉發。

工程師 M:負責將客服的需求參數轉換成最終的模型數據。職責有:對數據的操作、通知飛機模型更新。

工程師 C:協調 M 和 V。負責響應用戶、調用工程師M生成目標數據。

首先我們要知道,客戶提出了想要一個 60cm * 60cm 的飛機模型,這個需求到了製造商那裏肯定不是給出個 60cm * 60cm 的小方塊,而是根據需求計算處理生產真正的飛機模型(比如什麼樣的造型設計才能最大減少阻力),工程師M的工作之一就是根據原始數據並結合特定的邏輯規則給出最終的模型數據。

現在,用戶手裏有一飛機模型V,不過這個飛機模型的飛機雙翼和用戶想象的不一樣。於是用戶根據飛機模型上提供的方式反饋了問題(比如飛機模型提供了留言功能,用來收集用戶反饋)。工程師C收到了反饋後,把工程師M拉過來對數據進行處理並生成新的模型數據,並讓工程師M通知到共享相同數據的飛機模型去更新數據自主調整。

插一句,說到調整,我們有兩種方式。一個是,我們可以針對用戶不滿意的地方(飛機雙翼)進行調整。一個是,我們飛機模型格式化按照最新的數據模型重新初始化一下。前者可以認爲就是基於 DOM 操作的方式,後者就是基於數據的處理方式。

在 MVC 中,Model 和 View 之間耦合,視圖的更新需要 Model 去直接通知。Model 內因爲有 View 的引用才能讓視圖更新。

MVC.png

MVP

如果 Model 只想做數據相關的操作,把通知 View 的邏輯挪到了 Control 裏,這時 Control 搖身一變稱爲了 Presenter。因爲解耦了 Model 和 View,也使得它們的職責劃分更加清晰。

公司:飛機模型製造商 => 生產的飛機模型可以自主塑形。

模式:MVP

飛機模型 V:由模型數據生產出的模型。職責有:由模型數據自主塑形、將收集用戶反饋並轉發。

工程師 M:負責將客服的需求參數轉換成最終的模型數據。職責有:對數據的操作。

工程師 P:協調 M 和 V。負責響應用戶、調用工程師M生成目標數據、更新視圖。

在 MVP 模式中,工程師M的工作專注於數據,通知的活甩給了工程師P。
和 MVC 同樣的場景,工程師P接到反饋後,把工程師M拉過來處理了數據,然後又讓飛機模型依據已經處理後的數據自主調整。每次數據的變化都要主動去通知視圖更新。

MVP.png

MVVM

如果數據變化能夠自主觸發視圖更新,對 Presenter 來說也會輕鬆不少。於是 Presenter 再次搖身一變 稱爲了 ViewModel。

公司:飛機模型製造商 => 生產的飛機模型可以自主塑形。

模式:MVVM

飛機模型 V:由模型數據生產出的模型。職責有:由模型數據自主塑形、將收集用戶反饋並轉發。

工程師 M:負責將客服的需求參數轉換成最終的模型數據。職責有:對數據的操作。

工程師 VM:協調 M 和 V。負責響應用戶、調用工程師M生成目標數據並更新視圖。

MVVM.png

在 MVVM 中,View 和 Model 的變化似乎不大。爲了在數據變化後能夠自動更新視圖,ViewModel 進行了所謂的數據綁定。ViewModel 將 目標數據 和視圖進行了綁定,在最終生成目標數據時,會觸發視圖的更新。

在這裏我們可以想象有兩份數據,一份是源數據,一份是目標數據。綁定視圖的是目標數據,這樣,我們直接修改目標數據時會觸發視圖更新。如果是源數據經處理後賦給目標數據,目標數據也會改變,也會觸發試圖更新。

總之,在 MVVM 中,視圖是目標數據的可視化,通過改變視圖裏的數據也就等於改變了目標數據。

和 MVC、MVP 同樣的場景,不過科技發達了,工程師VM有個自動化處理程序。用戶反饋了問題,工程師VM的這個自動處理程序接到反饋自動處理並將結果發給飛機模型讓其自主調整。

以下是Vue的MVVM示意圖:
mvvmVue.png
MVC、MVP和MVVM大致就是如此,根據三種模式以及不同場景,最終演變出了不同的變體。

但是,不同的變體是針對不同問題的解決方案,指不定後來還會有 MVA、MVB..., 誰知道呢

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章