读书人

基于Backbone.js的JavaScript MVC示范

发布时间: 2013-10-30 12:56:21 作者: rapoo

基于Backbone.js的JavaScript MVC示例程序(4)
一.概述二.REST Server的实现2.1 REST API设计2.2 数据库设计2.3 用MyBatis实现的DAO层2.4 用Jersey实现的REST API2.5 用Spring AOP实现的日志功能三.前端的实现3.1 显示User列表3.2 显示User详细信息3.3 修改User信息3.4 增加User3.5 删除User3.6 添加validate3.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行)。

读书人网 >JavaScript

热点推荐