框架與庫的最大區別就是代碼的風格確認,庫只是頁面級別的選擇,而架構則關注於整個程序的設計css
做爲軟件中的99口訣,軟件設計要是沒個mvc就好像不是正規軍同樣,前端也是這樣,將html理解爲view,js理解爲controller,js的通信(主要指ajax)交互理解爲model的獲取,那麼前端就是一個標準的mvc架構,其寫法大體是這樣的html
html/view:前端
<button class="btn btn-info" id='save'>提交</button>
js/controller:ajax
$('#save').click(function() { $.post('/api/save').done(function(res) { consoel.log(res); }).fail(function(error) { consoel.log(error); }) });
ajax就是與model的交互後端
值得注意的是瀏覽器是基於事件觸發的,一切響應都基於事件,與咱們自定義的函數最大的區別就是其第一個參數必定爲event,因此也就能夠明確的代表js經過選擇器進行事件的賦值,以達到控制的目的,so...做爲一個前端理解爲mvc的架構師,就須要對其寫法進行簡單的肯定,好比:api
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
總之,前端的mvc大體就是將html看做view,一切與view無關的事情統統忽略(根據架構,可能會有1~2行的代碼用以描述controller),將js看做controller,其經過選擇器(即mvc中的接口)的方式獲取view並進行操做,並經過ajax與後臺(model)進行交互(M的概念一致比較弱化),以此達到解耦的目的框架
固然前端mvc包含mvc的全部缺點(依賴接口,更多的是接口太多,甚至沒法固定接口),尤爲在前端這種特殊的業務環境下,在其業務描述一定基於事件(這在前端確定避免不了)的前提下,類似的業務總會讓人措手不及,controller的描述也就變的無比蛋疼...
解決問題的辦法永遠都是分層,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是否是太耦合了...沒錯,單說耦合的話的確是這樣,但在前端大多數場景中,這種耦合是有必要的(尼瑪都是一我的寫,又不像先後端分離那樣明顯),這種耦合能夠消滅全部的接口創建,也就是所謂了無選擇器和自動執行的特色
mvc,mvp,mvvm進場在一塊兒比較的三胞胎,前端彷佛不流行mvp-。-
假設mvc是基礎,基於vc的強化叫mvvm,那基於vm的強化就叫mvp,model的獲取是經過ajax,前端根model已沒法在進行太多的封裝(在整就到後臺了),so...好像仍是沒有解釋mvp-。-
mvp大體就是充血模式吧,就醬紫
固然了,前端mvc和mvvm是各位大神根據實踐一步步總結出來的,而非想像上面簡單的分析出來的,這裏只是架構風格和業務寫法上作的簡單分析,更重要的區別仍是要給予實踐才能感覺到,任何架構都有適用的範圍,百數內的排序仍是快排好,買名牌仍是實體店放心,萬能架構仍是算了吧