原文:http://javascriptmvc.com/docs.html#&who=jQuery.Model
翻譯:劉貴學(liuguixue@gmail.com)
模型是用於封裝應用程式的資料層。對大型應用中來講,模型是非常重要的:
- 封裝服務,這樣控制層與視圖不需要關心資料從哪裡來;
- 提供輔助函數,使原始的商務資料執行與抽象更簡單
有兩種實現方法:
- 對服務要求或互動中擷取資料;
- 將原始的業務資料轉換或封裝成更有用的形式;
基本用法
jQuery.Model類提供了一個用於來組織您應用程式的資料層的基本架構。首先看一個Ajax操作不考慮模型的情況,假如我們有一個應用程式,需求如下:
- 檢索工作清單;
- 顯示每個任務的剩餘天數;
- 當使用者點擊後,標記完成
讓我們看一下不用模型如何?:
$.Controller.extend("MyApp.Controllers.Tasks",{onDocument: true},{ // 當頁面載入完成時,擷取所有任務 ready: function() { $.get('/tasks.json', this.callback('gotTasks'), 'json') }, /* 假設json是一個數組,如: * [{name: "trash", due_date: 1247111409283}, ...] */ gotTasks: function( json ) { for(var i =0; i < json.length; i++){ var taskJson = json[i]; //計算剩餘時間 var remaininTime = new Date() - new Date(taskJson.due_date); //追加到html $("#tasks").append("<div class='task' taskid='"+taskJson.id+"'>"+ "<label>"+taskJson.name+"</label>"+ "Due Date = "+remaininTime+"</div>") } },// 使用者點擊,標記完成//任務完成時, 擷取id, post一個請求,刪除 ".task click" : function( el ) { $.post('/tasks/'+el.attr('data-taskid')+'.json', {complete: true}, function(){ el.remove(); }) }})
此時代碼看起來也還好,但如果此時:
- 業務改變?
- 應用的其他部分也要計算剩餘時間?
- 其他部分也要擷取所有任務?
- 同一個任務要在頁面的不同地方顯示?
解決方案當然是需要一個強大模型層。在學寫一個model之前,讓我們看一下一個漂亮的模型的控制層如何?:
$.Controller.extend("MyApp.Controllers.Tasks",{onDocument: true},{ load: function() { Task.findAll({},this.callback('list')) }, list: function( tasks ) { $("#tasks").html(this.view(tasks)) }, ".task click" : function( el ) { el.model().update({complete: true},function(){ el.remove(); }); }})
views/tasks/list.ejs檔案內容如下:
<% for(var i =0; i < tasks.length; i++){ %><div <%= tasks[i] %>> <label><%= tasks[i].name %></label> <%= tasks[i].timeRemaining() %></div><% } %>
這樣做是不是好多了!當然,這些改善是因為我們使用了視圖,同樣也使我們的控制器完全可讀。那讓我們看一下模型:
$.Model.extend("Task",{ findAll: "/tasks.json", update: "/tasks/{id}.json"},{ timeRemaining: function() { return new Date() - new Date(this.due_date) }})
這樣更好了,因為您可以在一個單獨實現Ajax功能,並能在返回時封裝這些資料。讓我們
談談控制器與視圖中的每個加粗項。
Task.findAll
Task的findAll函數從"/tasks.json"請求資料,當資料返回時,先執行"wrapMany"函數後再傳給成功後的回呼函數。
如果你不知道回呼函數如何工作,您可以看一下wrapMany 與 callback.
el.model
jQuery.fn.model
是jQuery的協助工具輔助,它可以從html元素中返回一個模型的執行個體,list.ejs模板將所有的任務轉為html元素,做法如下:
<div <%= tasks[i] %>> ... </div>
剩餘時間timeRemaining
timeRemaining只是一個樣本函數,用於封裝您模型中的未經處理資料。
其他的好東西
以上這隻是關於模型功能的一個小嘗試,讓我們看看下面這些特性:
封裝
學會怎樣與服務互動:
$.Model("Task",{ findAll : "/tasks.json", findOne : "/tasks/{id}.json", create : "/tasks.json", update : "/tasks/{id}.json"},{})類型轉換
將"10-20-1982"的資料自動轉為 new Date(1982,9,20)
$.Model("Task",{ attributes : {birthday : "date"} convert : { date : function(raw){ ... } }},{})jQuery.Model.List
學習如何輕鬆處理多樣本:
$.Model.List.extend("Task.List",{ destroyAll : function(){ var ids = this.map(function(c){ return c.id }); $.post("/destroy", ids, this.callback('destroyed'), 'json') }, destroyed : function(){ this.each(function(){ this.destroyed() }); }}); ".destroyAll click" : function(){ this.find('.destroy:checked') .closest('.task') .models() .destroyAll();}驗證
驗證你模型的屬性
$.Model.extend("Contact",{init : function(){ this.validate("birthday",function(){ if(this.birthday > new Date){ return "your birthday needs to be in the past" } })},{});