框架與庫的最大區別就是代碼的風格確認,庫只是頁面級別的選擇,而架構則關注於整個程序的設計
MVC
作為軟件中的99口訣,軟件設計要是沒個mvc就好像不是正規軍一樣,前端也是這樣,將html理解為view,js理解為controller,js的通訊(主要指ajax)交互理解為model的獲取,那么前端就是一個標准的mvc架構,其寫法大致是這樣的
html/view:
<button class="btn btn-info" id='save'>提交</button>
js/controller:
$('#save').click(function() { $.post('/api/save').done(function(res) { consoel.log(res); }).fail(function(error) { consoel.log(error); }) });
ajax就是與model的交互
值得注意的是瀏覽器是基於事件觸發的,一切響應都基於事件,與我們自定義的函數最大的區別就是其第一個參數一定為event,所以也就可以明確的表明js通過選擇器進行事件的賦值,以達到控制的目的,so...作為一個前端理解為mvc的架構師,就需要對其寫法進行簡單的確定,比如:
js/controller-->更明確的controller結構
(function(){ //初始化 //將事件業務描述化 function save(event){ } $.controller.a={ '#save':{ click:save } } })()
$.controller為所有的控制器,其中的a就是改頁面的controller的內容,而后在結合簡單的架構封裝,比如路由或者在html上增加加載選項,就可以讓這個js作用於當前的view,當然這種寫法是用來描述的,在js加載器不斷完善,已融入為架構的一部分的情況下,controller早就可以更加的對象化,比如這樣:
define(function(require, exports, module) { //初始化參數 module.exports = { '#save':{ click:save } } //事件業務化 function save(event) { //.... } })
看着很熟悉吧,沒錯,用了seajs,加載器是架構的一部分,程序的設計就是api的設計(無視如何掉用的地方),單說這樣的寫法是不是讓人感覺更加的mvc呢?
總之,前端的mvc大致就是將html看作view,一切與view無關的事情通通忽略(根據架構,可能會有1~2行的代碼用以描述controller),將js看作controller,其通過選擇器(即mvc中的接口)的方式獲取view並進行操作,並通過ajax與后台(model)進行交互(M的概念一致比較弱化),以此達到解耦的目的
當然前端mvc包含mvc的所有缺點(依賴接口,更多的是接口太多,甚至無法固定接口),尤其在前端這種特殊的業務環境下,在其業務描述必定基於事件(這在前端肯定避免不了)的前提下,相似的業務總會讓人措手不及,controller的描述也就變的無比蛋疼...
mvvm
解決問題的辦法永遠都是分層,mvvm也是一樣,將基於事件的驅動,修正為基於方法,甚至基於屬性,就是一個更好的方式,mvvm的控制器並不會去監聽瀏覽器的事件,而是監聽一個屬性表,由瀏覽器的事件修改屬性,以觸發控制器中的方法,增加了一層控制業務的屬性,而這層屬性被稱為vm
舉個栗子:
假設一個分頁的業務,在兩種架構中m和v都一樣,則:
define(function(require, exports, module) { //初始化參數 var page=1,totalpage=10; module.exports = { '#pre':{ click:pre }, '#next':{ click:next }, '#last':{ click:last }, '#first':{ click:first } } //事件業務化 function pre(event) { page=(page===1)?1:page-1; exec(); } function next(event){ page=(page===totalpage)?totalpage:page+1; exec(); } //...last,first //總會有大量的通用業務,比如這個 function exec(){ $.ajax('/api/users',{ page:page, }) } })
依賴於屬性的變化,so...
define(function(require, exports, module) { //初始化參數 var page=1,totalpage=10; module.exports = { '#pre':{ click:pre }, '#next':{ click:next }, '#last':{ click:last }, '#first':{ click:first } } //事件業務化 function pre(event) { page=(page===1)?1:page-1; } function next(event){ page=(page===totalpage)?totalpage:page+1; } //...last,first //真正的業務,需要監控page屬性 $.watch('page',function(newv,oldv){ $.ajax('/api/users',{ page:page }) }); })
無視$.watch的存在,至少我們知道那里面包含的就是真正的業務邏輯,而所謂的事件,都只是用來修改屬性的對吧,就目前來講,他跟mvc還是很像,如果感覺到mvvm中的事件都只是修改屬性的特點的化,結合dom賦值的特點,在view中通過onclick屬性修改屬性標簽的化,就能夠將所有的接口(選擇器)全部的干掉...換而研制,依賴vm的變化,而非事件的變化,將業務的重點至於方法中而非事件中
如果了解js,html,css分離肯能會感覺到,在html中寫onclik是不是太耦合了...沒錯,單說耦合的話的確是這樣,但在前端大多數場景中,這種耦合是有必要的(尼瑪都是一個人寫,又不像前后端分離那樣明顯),這種耦合可以消滅所有的接口建立,也就是所謂了無選擇器和自動執行的特點
mvp
mvc,mvp,mvvm進場在一起比較的三胞胎,前端似乎不流行mvp-。-
假設mvc是基礎,基於vc的強化叫mvvm,那基於vm的強化就叫mvp,model的獲取是通過ajax,前端根model已無法在進行太多的封裝(在整就到后台了),so...好像還是沒有解釋mvp-。-
mvp大致就是充血模式吧,就醬紫
當然了,前端mvc和mvvm是各位大神根據實踐一步步總結出來的,而非想像上面簡單的分析出來的,這里只是架構風格和業務寫法上做的簡單分析,更重要的區別還是要給予實踐才能感受到,任何架構都有適用的范圍,百數內的排序還是快排好,買名牌還是實體店放心,萬能架構還是算了吧