淺談MVC/MVP/MVVM模式(MVC簡單實現)
經過之前的 在JavaScript中理解策略模式 、 在JavaScript中理解組合模式 、 淺談MVC/MVP/MVVM模式(概述) 和 較早之前的進擊的觀察者模式等文章的鋪墊,終於可以把這些理論的東西用於實踐了。
廢話不多說,直奔主題。
(以下程式碼可見部落格原文 或普通實現—codepen、 MVC實現-codepen 。)
GoF 並不將 MVC 引述為一種設計模式,而是把它看做是構建一個使用者介面的類的集合。按照他們的觀點,它實際上是三種經典設計模式的變異組合:觀察者模式,策略模式和組合模式。依賴於框架中的 MVC 如何實現,它也可能會使用工廠和模板模式。GoF Book 提到這些模式在使用 MVC 工作時是非常有用的附加功能。
功能示意:

由一組資料展示三類表格,分別是【stuff,scale】、【stuff,salary】、【stuff,scale,salary】三組檢視。另外可以修改指定 stuff 的 scale 或 salary 資訊。
stuffs 資訊:
const stuffs = [ { stuff: 'person_1', scale: '甲', salary: '6000' }, { stuff: 'person_2', scale: '乙', salary: '5000' }, { stuff: 'person_3', scale: '丙', salary: '9000' } ]; 複製程式碼
常規的寫法可以這麼來:

職責分配
既然說了 MVC 有那麼多好處,我們就用 MVC 的模式來改造下我們的程式碼。
首先我們先劃分下職責。
Model 負責對資料的處理並返回目標資料,在這個場景下是篩選 stuff、修改stuff 等職責。
View 負責對目標資料的渲染和處理使用者的響應,在這個場景下是各個表格的渲染、change 事件的委託等職責。
Control 負責協調 Model 和 View,在這個場景下是處理委託、處理資料等職責。
此處的 MVC 實現是針對一個 Model 對應多個 View 的程式碼實現, 也是為了把觀察者模式,策略模式和組合模式模式都用起來。
View
【stuff,scale】、【stuff,salary】、【stuff,scale,salary】三組檢視就是三個 View,每個 View 都可以獨立渲染自己的一組檢視。結合組合模式,我們我們造些檢視的葉物件和分支物件。

<html> <head></head> <body> <div id="app"></div> </body> </html> <script> const $APP = document.getElementById('app'); </script> 複製程式碼
葉物件(此處有兩類檢視):
const leafView_1 = () => { const renderTable = () => {...}; return { render: renderTable() }; } const leafView_2 = (Control) => { const $ONE = document.getElementById('one'); let $SCALE; let $SALARY; const renderSearchTable = params => {...}; const handleModify = e => {...}; const bindEvent = () => {...}; return { render: () => {...} }; } 複製程式碼
分支物件:
const branchView = (Control) => { let $SEARCH, $ALL; const Views = []; const addView = () => {...}; const render = () => {...}; const handleSearch = event => {...}; const bindEvent = () => {...} const initDOM = () => {...}; initDOM(); return { render, addView, }; }; 複製程式碼
Model
Model 主要是將資料處理成目標資料,並提供 View 註冊通知介面。
const Model = () => { let stuffData = []; let filterData = []; let Views = {}; const ajaxFun = () => [...]; // 模擬後臺獲取資料; const setStuffData = () => {}; const filterStuff = () => {}; const setFilterStuff = () => {}; const findStuff = () => {...}; const modifyStuffData = () => {...}; const register = () => {...}; const notify = () => {...}; return { setStuffData, setFilterStuff, modifyStuffData register, notify, }; } 複製程式碼
Control
鑑於此處有多類檢視,Model 和 View 之間,我們採用了釋出訂閱模式而不是觀察者模式。Model 需要收集 View,然後在資料改變時候更新檢視。
const Control = () => { const ModelInstance = Model(); const View_1 = () => {...}; const View_2 = () => {...}; const init = function () {...}; const filter = () => {...}; const modifyStuffInfo = () => {...}; return { init, filter, modifyStuffInfo }; }; 複製程式碼
MVC 程式碼實現:

後話
就這麼簡單的一個需求,改成 MVC 模式後就多了 100 多行程式碼。就如上篇文章所說一樣,如果是簡單的需求壓根沒必要這麼折騰。不過,改成 MVC 後,它們各自職責也就更加清晰了,對以後的維護也會好些。