當我們在使用一套框架或是架構的時候,多少都會好奇為什麼當初要這樣設計?以下將帶大家以React的視角,從MVC討論到MVVM。

關於React

首先必須要知道的是,React嚴格上來說,並非是一個完整的Framework,只能稱得上是Library。
像是Vue, React這種前端框架,就是種Library,和Angular提供的Solution不太一樣,主要原因是因為他們並沒有提供完整的解決方案來設計網頁,很多功能還是需要相依外部很多套件才能設計出玩網頁。

MVC架構

  1. Model
    • 資料型態與處理
  2. View
    • 畫面呈現
  3. Controller
    • 主要處理Model與View之間的邏輯

讓我們先撇開前端框架討論何謂MVC,如果要比照程式的話,大概就是:

  1. Model: Data
  2. View: HTML
  3. Controller: JavaScript

簡單來說就是,使用者瀏覽View來使用Controller更新Model。
這在早期的網頁架構其實很夠用了,從網頁操作到更新資料,最後再回去View更新顯示的資料。
流程看起來很合理也很正常,但是隨著網頁發展不斷的進步,大家開始發現一些問題:

  1. 每次更新View都一定要經過Controller更新一次Model。同理,更新Model的同時,也會更新一次View。
  2. 因為View的畫面呈現與Model的更新很緊密,因此兩者的耦合性很高,Model雖然更新了,但是對View來說,他並無法輕易地知道,接下來的畫面到底該如何呈現比較妥當,相似邏輯的程式難以再次拿來使用,需要撰寫更多邏輯相似的程式。
  3. Data Flow更新流程比較混亂,你可以想一下,View的顯示相依於Model的更新,Model的更新又可能促發View的更新,無法完全掌握實際的更新流程。

MVP架構


這時候就出現了MVP架構,試圖改善MVC架構的部份缺陷。基本上Controller負責的工作與MVC差不多,把命名改為Presenter,並且集中負責Model, View的Data flow。
此外,MVP也解決了MVC所遇到的顯示問題,View可以透過Presenter得知接下來的畫面該如何呈現給使用者比較妥當,例如同樣是陣列,可以透過一個action的呼叫,來改變畫面是要Table或是List呈現。

隨著時代的進步,大家對使用者體驗的胃口也越來越大,也因此彰顯出MVP架構的問題,那麼問題在哪呢?
你會發現MVP所改變的只是解決View和Model之間的問題,但是View和Controller之間的問題還是沒解決,要更新View的時候,一定要通過Presenter的執行,使用者還會收到接下來的畫面更新,以效率和流暢性來說,可以說是做了不少非必要的動作。

MVVM架構


看過MVC和MVP架構之後,再來看MVVM架構會比較知道在解決什麼問題。
現代流行的前端框架正是使用MVVM作為主流,讓使用者使用View的時候更流暢,View要更新畫面的時候,可以即時更新畫面所需要用到的資料。

以下為React結構中,你需要知道的:

  1. Model:在這你可以把React的this.state看成是Model,如果結合了React Redux,那麼store上Reducer各個的state也可以看成Model。這樣做的優點即可清楚的把資料和商務邏輯清楚的拆分,尤其從Redux的Actions和Reducers就可以看出邏輯和資料這兩部分是拆分的很清楚的。
  2. View Model:對應到React的JSX,但事實上本質是Virtual-DOM,React藉由檢查V-DOM的diff來優化整體畫面的流暢度,再解析成實體的DOM。
  3. View:對應到React解析V-DOM生成出來的實體DOM以及CSS。
  4. View Controller:負責View的動作,通常會在container上看到各別View分別具有哪些商務邏輯或執行的動作。
  5. Controller: 主要處理商務邏輯,不過通常討論MVVM上的Controller的時候,並不會特別去講。主要是因為Controller通常會直接在Model上去做討論,如:Redex的Actions。

單向綁定與雙向綁定

當我們在討論React的時候,對綁定的概念應該不陌生,例如:this.props.xxxx 正是讓特定scope的V-DOM綁定某部分的資料,而使用的方式。下面來介紹單向和雙向綁定的差別:

單向綁定

如果Model發生變化的話,會自動更新View Model。
很簡潔的一段話,但是什麼意思呢?我們比照上面類比的概念來理解這段話。

翻譯辭典

  • Model:對照於State
  • View Model:對照於V-DOM

翻譯蒟蒻

如果State發生變化的話,會自動更新V-DOM。
是不是很容易理解概念了?

雙向綁定

雙向綁定的概念就是Model更新的話,會自動更新View Model,而且View Model的更新也會影響到Model的更新。
聽起來好像有點混淆?在理解雙向綁定的時候,可能相對比較困難一些,不過其實只要記住一段話就能清楚牢記。
那就是:單向綁定 + 介面事件監聽 才可能發生雙向綁定
這也表示,表單也可以變成是單向綁定在處理介面的。
現在有很多方便的套件可以導入雙向綁定更易於使用,但是真的該使用雙向綁定嗎?

該用單向或是雙向綁定

我還是老話一句話,沒有任何一個技術或規則是絕對適合的。
不是每一個情境都適合單向或是雙向綁定。
單向綁定可以容易維護和追蹤資料,但是卻會讓我們的程式量很龐大。
回到雙向綁定,優點很顯而易見,但是缺點當然就是他多綁了,也代表自由度減少了。

例如:Redux套件的單向綁定對React來說就很夠用了。

為什麼React不原生雙向綁定

因為React出來的目的不是為了減少程式碼撰寫的量而生的
主要是為了讓程式碼簡潔, 清晰, 好維護,而且靈活度較大
相信很多喜歡使用React大於Vue的開發者,幾乎都是看上React的靈活度而選擇他,儘管技術門檻較高
Vue在框架中實現的雙向綁定就是一個活生生的例子,易於撰寫資料綁定,但是什麼時候改變了資料?什麼時候?
儘管Vue可以用watch去監聽,可是為什麼一定要在那邊去監聽呢?是不是開始意會到單向綁定的好處了

圖片來源

  1. progressbar
  2. githubusercontent
  3. journaldev