---
# System prepended metadata

title: MVVM (Model-View-ViewModel)
tags: [設計模式]

---

# MVVM (Model-View-ViewModel)
![MVVM](https://i.imgur.com/UBcyNz4.png)


MVVM(<font color=#0088FF>Model</font>-<font color=orange>View</font>-<font color=#00CC00>ViewModel</font>) 
- 是一種軟體架構模式
- 也被稱為 model-view-binder ，與 
    - MVP(<font color=#0088FF>Model</font>-<font color=orange>View</font>-<font color=#00CC00>Presenter</font>) 
    - PM(Presentation Model) 
 
    一樣都來自 MVC(<font color=#0088FF>Model</font>-<font color=orange>View</font>-<font color=#00CC00>Controller</font>) 模式

## 架構：

Model：
- 管理所有的**資料來源**(ex. API、資料庫)
- 管理後端的**業務邏輯處理**和**數據操控(CRUD)**

View：
- 在螢幕上 **顯示介面(UI)** 給使用者
- 接收**使用者與介面的互動( User Interaction )**
:::warning
- 前端主要由 HTML 和 CSS 來構建
- 通常是應用程序中的一個頁面，也可以是父視圖的子組件
:::



View Model：
- 負責處理 **<font color=orange>View</font> 的畫面邏輯/UI邏輯**(ex.事件處理、元件的互動/指令)
- 接收 **<font color=orange>View</font> 的指令(ICommand)**
- 並**對 <font color=#0088FF>Model</font> 請求資料**(ex.Ajax...method of Model Classes)
- 將 <font color=orange>View</font> 所需的**資料 保存/暫存**(輸入/顯示) 起來供 <font color=orange>View</font> 使用
:::success
- 前端主要由 JavaScript 來構建
- <font color=#00CC00>View Model</font> 為 <font color=orange>View</font> 與 <font color=#0088FF>Model</font> 的中介，也是 MVVM 的核心
- <font color=orange>View</font> 所使用的不是 <font color=#0088FF>Model</font> 的數據，而是 <font color=#00CC00>ViewModel</font> 的數據，由 <font color=#00CC00>ViewModel</font> 負責與 <font color=#0088FF>Model</font> 交流互動，這就完全解耦了 <font color=orange>View</font> 和 <font color=#0088FF>Model</font> ，這是以 **技術單位**-前後端 **關注點分離(Separation of Concerns , SoC)** 方案實施的重要一環。
:::

## MVVM原理：

- 利用 **Data Binding (Library)** 來實現 **Observer Pattern** 的概念
    - 由 <font color=orange>View</font> 來訂閱(subscribe) 在 <font color=#00CC00>ViewModel</font> 中所需要的資料
    - 並在**資料異動**時才更新 UI ( <font color=orange>View</font> )

- <font color=#00CC00>ViewModel</font> 使用 **ICommand介面** ，接收 <font color=orange>View</font> 的觸發，利用 
    - **[ 命令(ICommand)繫結、調用 <font color=#00CC00>ViewModel</font> 的 method ]** 
    -  **[ 調用 <font color=#0088FF>Model</font> classes 的 method  ]**
 
    分離 **<font color=#EEDD00>UI邏輯</font>** 與 **<font color=#715CA8>業務邏輯</font>**
- <font color=#00CC00>ViewModel</font> 使用 **INotifyPropertyChanged 屬性更改通知** 
    - 通知結繫端( <font color=orange>View</font> )，物件的屬性內容( <font color=#00CC00>ViewModel</font> )發生變更
    - 當結繫端( <font color=orange>View</font> )收到此通知便會進行 畫面(UI) 更新的動作

    即 **資料驅動(Data-Driven)** 而不是 事件驅動(Event-Driven)
:::danger
- 但是**過大資料繫結**會導致相當大的**記憶體消耗**
:::


## 與 MVC 的差別
核心的運作：
- <font color=#00CC00>ViewModel</font> 在繫結到 <font color=orange>View</font> 後，基本 上**不接收使用者的行為( User Interaction )**，而是使用 **命令(Command)** 來控制
- <font color=#00CC00>Controller</font> 包含 **接收使用者的行為( User Interaction )** 和 資料 Model 上的改變

畫面的更新：
- MVVM 的 <font color=orange>View</font> 使用 **Data Binding** 訂閱 <font color=#00CC00>ViewModel</font> 的 屬性更改通知
- MVC 的 <font color=orange>View</font> 監聽 <font color=#0088FF>Model</font> 的資料改變，同時也可能包括 Ajax 請求操作

>[【乾貨理解】理解javascript中實現MVC的原理](https://iter01.com/74230.html)

## 與 MVP 的差別
- 當 MVVM 的 <font color=#00CC00>ViewModel</font> 資料更新時，透過 **INotifyPropertyChanged 屬性更改通知**，來通知 <font color=orange>View</font> 更新
- 當 MVP 的 <font color=#0088FF>Model</font> 資料更新時，使用 **事件(Event)** 或是 **回呼函式(callback Function)** 給 <font color=#00CC00>Presenter</font> ，再由 <font color=#00CC00>Presenter</font> Call <font color=orange>View</font> 的更新 Function

> [MVP (Model View Presenter) 設計模式](http://programer-learn.blogspot.com/2014/09/mvp-model-view-presenter.html)

## MVVM流程：
- 當使用者跟 <font color=orange>View</font>(UI) 互動後，將命令傳給 <font color=#00CC00>ViewModel</font> 處理 
- <font color=#00CC00>ViewModel</font> 接收 <font color=orange>View</font> 的命令並對 <font color=#0088FF>Model</font> 請求資料
- <font color=#00CC00>ViewModel</font> 收到 <font color=#0088FF>Model</font> 的資料後，做資料的暫存，或是處理成 <font color=orange>View</font> 所需要的格式
- <font color=#00CC00>ViewModel</font> 通知 <font color=orange>View</font> 資料變更
- <font color=orange>View</font> 更新畫面

## MVVM優劣：
- 開發人員和設計人員可以更加獨立於各自的領域，達到關注點分離(Separation of Concerns)
- 開發人員可以專注於 <font color=#00CC00>ViewModel</font> 、 <font color=#0088FF>Model</font> ，可以在不使用 <font color=orange>View</font> 的情況下為 <font color=#00CC00>ViewModel</font> 和 <font color=#0088FF>Model</font> 創建**單元測試**
- 設計人員可以專注於 <font color=orange>View</font> 的 **UI** 與 <font color=#00CC00>ViewModel</font> **UI邏輯**，也可以在 <font color=#00CC00>ViewModel</font> 輕鬆生成 <font color=orange>View</font> 所需要的**範例數據**以進行處理


<br><br><br><br><br>
參考如下：
> [程式設計師應該知道的MVC，MVP，MVVM設計模式區別及優缺點
](https://kknews.cc/zh-tw/news/8qzkmog.html)

> [MVP(SC)、MVP(PV)、PM、MVVM 和 MVC 表現模式架構對比](https://developer.aliyun.com/article/380256)

> [Binding ICommand (命令繫結)](https://me1237guy.pixnet.net/blog/post/67837890)

> [邏輯移到ViewModel](https://skychang.github.io/2011/12/31/WPF-%E2%80%93-MVVM-%E4%B8%89/#:~:text=%E4%BA%86%E7%94%9A%E9%BA%BC%E8%AE%8A%E5%8C%96%E3%80%82-,%E9%82%8F%E8%BC%AF%E7%A7%BB%E5%88%B0ViewModel,-%E5%88%B0%E9%80%99%E9%82%8A%EF%BC%8C%E6%88%91)

> [WPF 的 MVVM 測試](http://radio-idea.blogspot.com/2018/12/wpf-mvvm.html)

> [The MVVM Pattern](https://docs.microsoft.com/en-us/previous-versions/msp-n-p/hh848246(v=pandp.10)?redirectedfrom=MSDN)

> [MVVM架構](https://ithelp.ithome.com.tw/articles/10192829)

> [MVVM模式](https://www.twblogs.net/a/5b8395d32b71776c51e3b1de)

###### tags: `設計模式`