我們將通過建立名叫todo的應用程式來介紹javascriptMVC各項準系統。
擷取JavascriptMVC
你可以通過下載或者使用git的方式得到JavascriptMVC,:https://github.com/downloads/jupiterjs/javascriptmvc/javascriptmvc-3.2.4.zip。他由四個子項目組成,一旦你獲得javascriptMVC,你將會得到下面的目錄結構,目前的目錄就是根目錄:
documentjs - 文檔引擎funcunit - 測試應用jquery - jquery 和 jQueryMX 外掛程式steal - 依賴管理工具js - Linux/Mac js命令列工具js.bat - Windows js命令列工具
運行JavascriptMVC
jmvc使用steal/steal.js作為依賴管理工具,可以用它來載入js檔案,比如你要使用steal載入 $.Controller 和 $.View,可以用下面的方式:
steal('jquery/controller','jquery/view/ejs',function(){ //使用 controller 和 view 的地方})
要使用steal,你需要在頁面中添加steal標籤。在根目錄下添加todos目錄,空的todos.html 和todos.js,像這樣:
ROOT\ documentjs\ jquery\ funcunit\ steal\ todos\ todos.js todos.html
為了載入steal.js和todos.js,todos.html內容如下:
<!DOCTYPE html><html><head></head><body> <ul id='todos'></ul> <input id='editor'/> <script type='text/javascript' src='../steal/steal.js?todos/todos.js'> </script></body></html>
可以使用firefox瀏覽器開啟頁面,用firebug查看steal.js 和 todos.js 的載入情況。
steal steal([paths])
steal用於載入js、css、CoffeeScript、LESS和模版檔案到你的應用程式。steal的路徑和根路徑有關,無論引用下面的代碼的分頁檔在什麼目錄下,都會去根目錄下載入jquery/class/class.js。
steal('jquery/class/class.js');
在前面的《javascriptMVC入門 -- 11.StealJS -> steal》的課程中也有提到,這種寫法和下面的寫法是等價的:
steal('//jquery/class/class.js');
引用相對於當前路徑檔案可以在路徑前面加 ./ :
steal('./helpers.js')
steal也支援載入css檔案,
steal('./todos.css')
前面的課程也提到,載入jquery/class/class.js可以用下面的方式:
steal('jquery/class')
因為steal是非同步記載,所以不要用下面的方式:
steal('jquery/class')$.Class //載入jquery/call之後才能做的事情
取而代之,使用下面的方式:
steal('jquery/class', function(){ $.Class //載入jquery/class之後才做的事情})
在我們todos應用程式中,我們要載入和jqueryMX相關外掛程式檔案到todos.js檔案中:
steal('jquery/class', 'jquery/model', 'jquery/dom/fixture', 'jquery/view/ejs', 'jquery/controller', 'jquery/controller/route', function($){})
接下來我們就來看要用到的jqueryMX相關外掛程式。
$.Class $.Class([name,] [classProps,] [prototypeProps])
使用$.Class的建構函式建立類的執行個體,會包含共用屬性,$.Controller,$.Model就是通過它建立的。使用$.Class建立自己的類,需要你提供下面的參數:
- name:類的名字,可以用於類的自我描述;
- classProperties:靜態屬性,可以使用constructor對象使用;
- prototypeProperties:原型屬性,類的執行個體使用。
$.Class使用原型鏈式,所以你可以根據需要擴充需要的子類:
steal('jquery/class', function(){ $.Class("Todo",{ init : function(){}, author : function(){ ... }, coordinates : function(){ ... }, allowedToEdit: function(account) { return true; } }); Todo('PrivateTodo',{ allowedToEdit: function(account) { return account.owns(this); } })});
$.Class提供_super方法,可以在訪問原型鏈上一級名字相同的函數,可以理解為訪問父級函數:
var SecureNote = Todo({ allowedToEdit: function(account) { return this._super(account) && this.isSecure(); }})
constructor/init new Class(arg1, arg2)
當類的建構函式調用的時候,$.Class會建立執行個體對象,並把參數傳遞給$.Class.prototype.init,執行init方法。在實行init方法之前,還會執行setup方法,他可以用來影響傳遞給init方法的參數。
$.Class('Todo',{ init : function(text) { this.text = text }, read : function(){ console.log(this.text); }})var todo = new Todo("Hello World");todo.read()
Model $.Model(name, classProperties, prototypeProperties)
Model是任何應用的中心,他們包含資料和商務邏輯。你可以擴充$.Model,實現你自己的方法,同時他提供了一系列的方法用於管理執行個體的改變。建立一個Model執行個體,你需要傳遞下面參數:
- name:類的名字;
- classProperties:靜態屬性,包括findAll, findOne, create, update,destroy屬性;
- prototypeProperties:原型屬性,類的執行個體使用。
用下面的方式,在todos.js中建立一個Todo model:
steal('jquery/class', 'jquery/controller', 'jquery/model', 'jquery/view/ejs', 'jquery/dom/fixture', function($){ $.Model('Todo',{ findAll : "GET /todos", findOne : "GET /todos/{id}", create : "POST /todos", update : "PUT /todos/{id}", destroy : "DELETE /todos/{id}" }, {})});
note:你可以在瀏覽器的命令框中使用下面的命令。
new $.Model(attributes)
建立一個todo的執行個體:
var todo = new Todo({name: "do the dishes"});
attr model.attr(name,[value])
$.Model.prototype.attr 讀取或者設定model執行個體的屬性。
todo.attr('name') //-> "do the dishes"todo.attr('name', "wash the dishes" );todo.attr('name') //-> "wash the dishes"
瀏覽器中的執行結果,我使用的時chrome瀏覽器:
與伺服器互動
Model使用靜態findAll、findOne、create、update 和 destroy 方法,去 create、read、update 和 delete 伺服器上的執行個體。你現在可以使用Todo上的靜態方法,修改伺服器上的資料了,在命令列輸入下面的語句:
Todo.findAll({});
他會向伺服器請求 GET /todos,運行結果:
你可以使用 $.fixture 類比該請求。
$.fixture $.fixture(url, fixture(original, settings, headers) )
$.fixture類比一個特定url的請求,他會使用到下面的參數:
- original:傳遞給$.ajax的原始設定;
- settings:$.ajax地標準設定;
- header:要求標頭。
期待返回的結果是下面的數組形式:
return [ status, statusText, responses, responseHeaders ];
實際結果可能像這樣:
return [ 200, "success", {json: []}, {} ];
如果返回數組只有一個值,那麼就假設他是json類型的資料。把下面的代碼載入steal的回呼函數中,用來類比todo伺服器:
// todos listsvar TODOS = [ {id: 1, name: "wake up"}, {id: 2, name: "take out trash"}, {id: 3, name: "do dishes"}];// findAll$.fixture("GET /todos", function(){ return [TODOS]});// findOne$.fixture("GET /todos/{id}", function(orig){ return TODOS[(+orig.data.id)-1];})// createvar id= 4;$.fixture("POST /todos", function(){ return {id: (id++)}})// update$.fixture("PUT /todos/{id}", function(){ return {};})// destroy$.fixture("DELETE /todos/{id}", function(){ return {};})
現在你可以使用Model的ajax方法執行對todos執行CRUD操作了。
findAll findAll( params, success( todos ), error() )
findAll擷取多個todo執行個體:
Todo.findAll({}, function( todos ) { console.log( todos );})
運行結果:
findOne findOne( params, success( todos ), error() )
findOne擷取一個todo執行個體:
Todo.findOne({}, function( todo ) { console.log( todo );})
運行結果:
save todo.save( success( todo ), error() )
save判斷伺服器上執行個體是否被建立,沒建立則執行create方法,建立了則執行update方法。下面的例子建立一個todo執行個體,執行save方法:
var todo = new Todo({name: "mow lawn"})todo.save(function(todo){ console.log( todo );})
運行結果:
下面的例子建立todo執行個體,修改他的屬性執行save方法:
var todo = new Todo({name: "mow lawn"});todo.save( function(todo){ console.log("created", todo ); todo.attr("name", "mow my lawn") todo.save( function( todo ) { console.log("updated", todo ); })})
運行結果:
上面是代碼執行的效果,我們可以看到他向伺服器發送了兩次請求。但是這裡有意思的是,兩次返回的class結果是一樣,彷彿{name: "mow lawn"}沒有起到作用,是不是第一次請求失敗了?其實是因為兩次顯示的都是最後一次的執行結果,第一次請求還是正常運行了的。
destroy todo.destroy( success( todo ), error() )
destroy方法從伺服器上刪除一個執行個體。
var todo = new Todo({name: "mow lawn"});todo.save( function(todo){ console.log("created", todo ); todo.destroy( function( todo ) { console.log("destroyed", todo ); })})
運行結果:
bind todo.bind( event, handler(ev, todo ) )
可以用bind來監聽單個或者所有todo執行個體的改變,例如下面的例子實現對todo created的監聽:
var todo = new Todo({name: "mow lawn"});todo.bind('created', function(ev, todo){ console.log("created", todo );})todo.save()
運行結果:
通過下面的方式,實現對所有todo執行個體 created 的監聽:
Todo.bind('created', function(ev, todo){ console.log("created", todo );})
Model提供對類和執行個體的監聽事件包括:
- created - 執行個體在伺服器上建立
- updated - 執行個體在伺服器上更新
- destroyed - 執行個體在伺服器上銷毀
$.fn.model $(el).model([modelInstance])
用一個model執行個體標記一個html元素可能會相當有用,他可以檢索到。jQuery.fn.model 用於在一個html元素上設定或者擷取一個model執行個體,就像下面的例子:
var li = $('<li>').model( new Todo({id: 5}) ) .appendTo("#todos");
他會添加‘todo todo_5’到‘li’ 的className中,運行結果:
我們可以用下面的方式擷取model執行個體:
li.model().id //-> 5
運行結果:
elements todo.elements( [context] )
可以使用Elements擷取到那些包含model執行個體的html元素,可以使用jquery的context限定查詢範圍,例如下面的例子:
todo.elements('#todos');
javascriptMVC教程目錄