基於Backbone.js的JavaScript MVC示例程序(4)


3.1 顯示User列表

界面如下:

1.html文件

 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
 2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 3 <html>
 4 <head>
 5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 6 <script src="./js/jquery.js"></script>
 7 <script src="./js/underscore.js"></script>
 8 <script src="./js/backbone.js"></script>
 9 <script src="./js/mvc1.js"></script><!-- 引入js文件 -->
10 <script type="text/template" id="user-item-template"><!-- html模板 -->
11     <span>(<%= id %>)</span><a href="#"><%= username %></a>
12 </script>
13 <link rel="stylesheet" type="text/css" href="./css/default.css" />
14 <title>MVC 1</title>
15 </head>
16 <body>
17     <div id="main">
18         <div id="left">
19             <h3></h3>
20             <ul id="user-list"></ul>
21         </div>
22         <div id="right"></div>
23     </div>
24 </body>
25 </html>

 mvc1.js文件

 1 $(document).ready(function() { //注釋一
 2     
 3     //定義User
 4     var User = Backbone.Model.extend({
 5     });
 6     
 7     //定義UserList,是User的集合
 8     var UserList = Backbone.Collection.extend({
 9         model : User,
10         url : "/backbone-sample/rest/user", //注釋二
11         /*****重載fetch****
12         fetch : function() {
13             var self = this;
14             $.ajax({
15                 url: self.url,
16                 cache:false,
17                 type: 'GET',
18                 async: true,
19                 dataType: 'json',
20                 timeout: 300000,
21                 success: function( data, textStatus ) {                            
22                     self.reset(data.user);
23                 },        
24             });
25         }
26         *************/
27     });
28     
29     //定義UserItemView,用來顯示用戶列表中的一個條目
30     var UserItemView = Backbone.View.extend({
31         tagName : "li",
32         userItemTemplate : _.template($("#user-item-template").html()), //綁定模板
33         render : function() {
34             this.$el.html(this.userItemTemplate(this.model.toJSON()));
35             return this;
36         },
37     });
38     
39     //定義UserListView,用來顯示用戶列表
40     var UserListView = Backbone.View.extend({
41         el : $("#main"),
42         initialize : function() {
43             this.userList = new UserList();
44             this.userList.bind('reset', this.addAll, this);
45             this.userList.bind('all', this.render, this); //注釋三
46             this.userList.fetch({silent: true, success:function(collection, response){ //注釋四
47                 if(response != null){
48                     collection.reset(response.user);
49                 }else{
50                     userListView.render();
51                 }
52             }});
53         },
54         render : function() {
55             this.$("#left h3").html("Total Number:"+this.userList.length);
56         },
57         addOne : function(user) {
58             var view = new UserItemView({model : user});
59             this.$("#user-list").append(view.render().el);
60         },
61         addAll : function() { 
62             this.userList.each(this.addOne);
63         },
64     });
65     
66     var userListView = new UserListView();//注釋五
67 });

 

 注釋一:

一開始列表內容顯示不出來,找了半天沒找到原因,后來才發現是忘記加document.ready了。

注釋二:

Model 里面各有一個 url() 方法,和一個 urlRoot 屬性;Collection 里面有一個 url() 方法,它們的關系如下:

model.url() 返回模型資源在服務器上位置的相對 URL,默認的的實現是:如果模型包含在某個集合中,則生成 URL 的形式為:"/[collection.url]/[id]"; 如果模型不是集合的一部分,則 URL 形式為:"/[urlRoot]/id"。當然可以自己重載這個方法。

例如:一個 id 為101的模型,存儲在url為 "/documents/7/notes" 的 Colletion 中, 那么該模型的 URL 為:"/documents/7/notes/101"。

一般 GET、PUT、DELETE 是對某個特定模型的操作,會用 model.url() 得到帶有 id 的模型 URL;而 POST 操作是不知道模型id的,因此會用 collection.url() 得到集合的 URL。

在本例中,User 包含在 UserList 中,因此需要指定 UserList 的 url。

注釋三:

官網上對於bind方法的解釋:object.bind(event, callback, [context])

綁定 callback 函數到 object 對象。 當事件觸發時執行回調函數 callback 。如果一個頁面中有大量不同的事件,按照慣例使用冒號指定命名空間:"poll:start"或"change:selection"。當 callback 執行時提供第三個可選參數,可以為 this 指定上下文: model.bind(‘change’, this.render, this)綁定到特殊事件 "all" 的回調函數會在任意事件發生時被觸發,其第一個參數為事件的名稱。

注意到第三個參數,指定了第二個參數中this所代表的對象,例如:如果把this.userList.bind('add', this.addOne, this)的this去掉,那么實際執行的時候,this.addOne中的this會是userList,實際上應該是userListView,於是就會出錯。

還有一點,在Todos這個例子中,所有的事件都是使用on來綁定事件的,也就是this.userList.on('add', this.addOne, this),我試了一下,二者沒有什么區別。查了一下源碼,on是定義在Backbone.Events中的一個函數,暫時還沒能理解為什么二者是等價的。

on: function(events, callback, context) {…} // Bind one or more space separated events, `events`, to a `callback` function. Passing `"all"` will bind the callback to all events fired.

注釋四:

官網上對於Collection的fetch函數的解釋如下:collection.fetch([options]) 

從服務器拉取集合的默認模型,成功接收數據后會重置(reset)集合。options 支持 success 和 error 回調函數,回調函數接收 (collection, response) 作為參數。 可以委托 Backbone.sync 在隨后處理個性化需求。處理 fetch 請求的服務器應當返回模型的 JSON 數組。

也就是調用 UserList 的 fetch() 方法時,會自動對 model.url() 的地址發出GET請求,然后將接收到的 JSON 數組作為參數來調用 reset() 方法自動設置UserList里面的User數組。

在我Server端,返回的Userlist格式如下:

{"user":[{"id":"63","username":"Andy0011","password":"123123","email":"111111@1.com","phone":""},…]}

 注意到最外面會有一個 "user",這樣的格式不能被默認的fetch函數使用來給集合設值,因此需要自己重載fetch函數。

有兩個方法來實現:

第一個方法是在調用fetch函數的時候使用success回調函數,如注釋四 fetch() 中的代碼塊所示。

注意到有一個 silent: true,這是因為 fetch() 是異步的,當運行完之后自動觸發 reset 事件來給 userList 賦值,但是這個時候服務器端的JSON還沒有返回來,所以會報錯。加上 silent: true 之后,就不會自動觸發reset事件了,而是在success回調函數中使用 response.user 作為參數手動調用reset函數來給userList賦值。當然如果數據庫里面是空的就會返回空,因此需要判斷一下,區分處理。

第二個方法更加靈活了,是在var UserList = Backbone.Collection.extend({ })這個里面重載fetch函數,如11-26行注釋中的代碼塊所示。

這是一個典型的jQuery ajax調用,將請求設置為同步是為了解決上面那個silent: true的問題。

注釋五:

需要初始化一個 UserListView 類型的對象,頁面顯示的流程是:

調用 UserListView 的 initialize() 方法(42行),在其中將2個方法綁定到了 userList 的事件上(44-45行),並調用了 userList 的 fetch() 放來從Server 獲取數據並給其賦值(46行),在賦值的時候調用了 userList 的 reset() 方法(48行),這時候會觸發已綁定的 "reset" 事件,並調用 UserListView 的 addAll() 方法顯示列表內容,同時也會觸發 "all" 事件,並調用UserListView 的 render() 方法在列表頭部現實列表長度。在 addAll() 方法中為userList中的每一個元素調用 addOne() 方法(57行),在 addOne() 方法中會創建一個 UserItemView 並用它顯示列表的一個條目(61行)。

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM