Backbone.js入门实战:WEB端MVC框架开发单页应用实战(txt+pdf+epub+mobi电子书下载)


发布时间:2020-06-01 18:39:47

点击下载

作者:the5fire

出版社:中信出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Backbone.js入门实战:WEB端MVC框架开发单页应用实战

Backbone.js入门实战:WEB端MVC框架开发单页应用实战试读:

第一版前言

写在前面的话

这一系列的文章写了这么久,也算是告一段落了,为了方便大家查看,制作成PDF格式的放到网上,待有兴趣学习 backbone.js的同学参考。

第一次写完一系列的东西,以前有过很多写系列文章的冲动,不过都是写了一段时间就因为一些事放下了,如:设计模式,还有tomcat源码。

其实这一系列文章的主要目的还是让初学backbone.js的人,能够快速的把它用到项目上。写backbone的原因是,在我搜索查找关于它的学习资料时,发现中文的资料比较少也比较散,所以就一边学习,一边把里面的东西大概的梳理了一下,写成文章,希望可以分享给大家。

任何一个人都是从菜鸟慢慢成长起来的,而你成长过程中的所有经历恰恰又是下一代或者说你后面菜鸟所渴望知道的,同时也是对你以后成长大有帮助的。所以不管你觉得自己有多菜,你都应该把你学到的,思考的东西写下来,哪怕只有一点。

所有的文章中会有很多不足的地方,你如果发现错误,欢迎到对应的博文链接上拍砖。每篇文章都给了链接,方便大家快速跳转到网页。

最后,写上一句话,以显示我的文学水平(表拍砖):没有开始,怎么会有成长;没有总结,怎么会有收获;没有分享,怎么会有升华。

第二版前言

一年前写的东西,当时写完之后工作中用不到也就不再看了,谁想后来越来越多的人通过搜索backbonejs来到我的博客,有表示感谢的,有吐槽的,有帮忙改bug的。在之前接触时只是为了能让代码运行,因此很多实例没有考虑版本问题。在backbonejs更新到1.0.0之后,我的很多代码实例都出现了问题,于是我不得不去更新其中的东西。但是这样一点点的更新总是不能覆盖全面,随想不如在搞个第二版,把之前的坑填上,然后再补充点我新学到的东西,尽可能的让有机会看到这本电子书的人有点收获。

说起这一年,学习了angularjs,还没有来得及实践。用backbonejs实践了我博客的手机版:m.the5fire.com功能,比较简陋。

在qq群里聊天时@wrongway兄调侃说backbonejs属于远古时期的框架了,关于这一点,相比于angularjs确实显的有些落后。在我看来,两个的思路或者哲学并不相同,backbonejs就如其官网所说提供了一个web应用的结构,而angularjs则是对html的增强。

大概就闲扯这么多,总之主要的目的是填上一版的一些坑,然后或许会留下新的坑。

从去年8月份开始到现在,最初的目的算是完成了。但是随着不断地和正在学习Backbone.js的人交流发现,有些人虽然已经掌握了Backbone.js基本模型、视图以及其他模块的使用,但是却无法把已掌握的内容转化到实际项目中。

另外大家也看厌了到处在分析的Todos这个实例,希望看到真实点的项目。虽然对大家看待优秀项目代码的态度不太认同,但我很理解初学者的这种心情——不要给我Demo,我要真实的东西。

但真实的东西往往需要太多其他方面的知识,比如我在最后的项目中用到了socket.io来实现实时的交流。这些东西都算是超出Backbone.js这个框架内容之外的。

要学习一个东西,和结识一个新的朋友一样。如果你总是站在远处想看风景一般看着他/她,那他/她对你来说只能是风景。对于Backbone.js来说也一样,不要停留在看完书、觉得会用的阶段,拉起Ta的手,一起来做一些东西。

基于此,最后的那个项目是打算放到线上来运行的,也让读完本书的读者能有一个地方体验一下你在本书看到的东西,最终是如何转化为被用户可用的网站的。第1章Hello Backbonejs1.1 基础概念

Backbone,英文意思是:勇气、脊骨,但是在程序里面,尤其是在Backbone后面加上后缀js之后,它就变成了一个框架,一个js库。

Backbone.js,不知道作者是以什么样的目的来对其命名的,可能是希望这个库会成为web端开发中脊梁骨。

好了,八卦完了开始正题。

Backbone.js提供了一套web开发的框架,通过Models进行key-value绑定及自定义事件处理,通过Collections提供一套丰富的API用于枚举功能,通过Views来进行事件处理及与现有的Application通过RESTful JSON接口进行交互.它是基于jQuery和underscore的一个前端js框架。

整体上来说,Backbone.js是一个web端javascript的MVC框架,算是轻量级的框架。它能让你像写Java(后端)代码组织js代码,定义类,类的属性以及方法。更重要的是它能够优雅的把原本无逻辑的javascript代码进行组织,并且提供数据和逻辑相互分离的方法,减少代码开发过程中的数据和逻辑混乱。

在Backbonejs有几个重要的概念,先介绍一下:Model,Collection,View,Router。其中Model是根据现实数据建立的抽象,比如人(People);Collection是Model的一个集合,比如一群人;View是对Model和Collection中数据的展示,把数据渲染(Render)到页面上;Router是对路由的处理,就像传统网站通过url现实不同的页面,在单页面应用(SPA)中通过Router来控制前面说的View的展示。

通过Backbone,你可以把你的数据当作Models,通过Models你可以创建数据,进行数据验证,销毁或者保存到服务器上。当界面上的操作引起model中属性的变化时,model会触发change的事件。那些用来显示model状态的views会接受到model触发change的消息,进而发出对应的响应,并且重新渲染新的数据到界面。在一个完整的Backbone应用中,你不需要写那些胶水代码来从DOM中通过特殊的id来获取节点,或者手工的更新HTML页面,因为在model发生变化时,views会很简单的进行自我更新。

上面是一个简单的介绍,关于backbone我看完他的介绍和简单的教程之后,第一印象是它为前端开发制定了一套自己的规则,在这个规则下,我们可以像使用django组织python代码一样的组织js代码,它很优雅,能够使前端和server的交互变得简单。

在查backbone资料的时候,发现没有很系统的中文入门资料和更多的实例,所以我打算自己边学边实践边写,争取能让大家通过一系列文章能快速的用上Backbone.js。

关于backbone的更多介绍参看这个:

http://documentcloud.github.com/backbone/

http://backbonetutorials.com/1.2 backbone的应用范围

它虽然是轻量级框架,但是框架这东西也不是随便什么地方都能用的,不然就会出现杀鸡用牛刀,费力不讨好的结果。那么适用在哪些地方呢?

根据我的理解,以及Backbone的功能,如果单个网页上有非常复杂的业务逻辑,那么用它很合适,它可以很容易的操作DOM和组织js代码。

豆瓣的阿尔法城是一个极好的例子——纯单页、复杂的前端逻辑。

当然,除了我自己分析的应用范围之外,在Backbone的文档上看到了很多使用它的外国站点,有很多,说明Backbone.js还是很易用的。

稍稍列一下国内用到Backbone.js的站点:

1. 豆瓣阿尔法城 链接:http://alphatown.com/

2. 豆瓣阅读 链接:http://read.douban.com/ 主要用在图书的正文页

3. 百度开发者中心 链接:http://developer.baidu.com/

4. 手机搜狐直播间 链接:http://zhibo.m.sohu.com/

5. OATOS企业网盘 链接:http://app.oatos.com1.3 学以致用

现在,我们就要开始学习Backbone.js了,我假设你没有看过我的第一版,那一版有很多很多问题,在博客上也有很多人反馈。但是如果你把那一版看明白了,这新版的教程你可以粗略的浏览一遍,不过后面新补充的实践是要自己写出来、跑起来的。

先说我们为什么要学习这新的东西呢?简单说来是为了掌握更加先进的工具。那为什么要掌握先进的工具呢?简单来说就是为了让我们能够以更合理、优雅的方式完成工作,反应到代码上就是让代码变得可维护、易扩展。如果从复杂的方向来说的话,这两个话题都够我写好几天的博客了。

学以致用,最直接有效的就是用起来,光学是没用的,尤其是编程这样的实践科学。新手最常犯的一个错误就是喜欢不停地去看书,看过了就以为会了,然后就开始疯狂的学下一本。殊不知看懂和写出来能运行是两种完全不同的状态。因此建议新手——编程新手还是踏踏实实的把代码都敲了,执行了,成功了才是。

下面直接给一个简单的Demo出来,用到了Backbonejs的三个主要模块:Views、Collection、Model。通过执行这个例子,了解这个例子的运行过程,快速对要做的东西有一个感觉,然后再逐步击破。1.4 完整DEMO

这个Demo的主要功能是点击页面上得“新手报到”按钮,弹出对话框,输入内容之后,把内容拼上固定的字符串显示到页面上。事件触发的逻辑是: click 触发checkIn方法,然后checkIn构造World对象放到已经初始化worlds这个collection中。

来看完整的代码: the5fire.com-backbone.js-Hello World

更多教程

这里面涉及到backbone的三个部分,View、Model、Collection,其中Model代表一个数据模型,Collection是模型的一个集合,而View是用来处理页面以及简单的页面逻辑的。

动手把代码放到你的编辑器中吧,成功执行,然后修改某个地方,再次尝试。第2章 Backbonejs中的Model实践

上一章主要是通过简单的代码对Backbone.js做了一个概括的展示,这一章开始从Model层说起,详细解释Backbonejs中的Model这个东西。

对于Model这一部分,其官网是这么说的:“Model是js应用的核心,包括基础的数据以及围绕着这些数据的逻辑:数据转换、验证、属性计算和访问控制。”这句话基本上高度概括了Model在一个项目中的作用。实际上,不仅仅是js应用,在任何以数据收集和处理的项目中Model都是很重要的一块内容。

Model这个概念在我的印象中是来自于MVC这个东西,Model在其中的作用,除了是对业务中实体对象的抽象,另外的作用就是做持久化,所谓持久化就是把数据存储到磁盘上——文件形式、数据库形式。在web端也有对应的操作,比如存入LocalStorage,或者Cookie。

在Web端,Model还有一个重要的功能就是和服务器端进行数据交互,就像是服务器端的程序需要和数据库交互一样。因此Model应该是携带数据流窜于各个模块之间的东西。

下面让我们通过一个一个的实例来逐步了解Model。

先定义一个页面结构,实践时须在注释的地方填上各小节的代码: the5fire-backbone-model 2.1 最简单的对象var Man = Backbone.Model.extend({ initialize: function(){ alert('Hey, you create me!'); }});var man = new Man;

这个确实很简单了,只是定义了一个最基础的Model,只是实现了initialize这个初始化方法,也称构造函数。这个函数会在Model被实例化时调用。2.2 对象属性赋值的两种方法

第一种,直接定义,设置默认值。var Man = Backbone.Model.extend({ initialize: function(){ alert('Hey, you create me!'); }, defaults: { name:'张三', age: '38' }});var man = new Man;alert(man.get('name'));

第二种,赋值时定义。var Man = Backbone.Model.extend({ initialize: function(){ alert('Hey, you create me!'); }});var man = new Man;man.set({name:'the5fire',age:'10'});alert(man.get('name'));

从这个对象的取值方式可以知道,属性在一个Model是以字典(或者类似字典)的方式存在的,第一种设定默认值的方式,只不过是实现了Backbone的defaults这个方法,或者是给defaults进行了赋值。2.3 对象中的方法var Man = Backbone.Model.extend({ initialize: function(){ alert('Hey, you create me!'); }, defaults: { name:'张三', age: '38' }, aboutMe: function(){ return '我叫' + this.get('name') + ',今年' +this.get('age') + '岁'; }});var man = new Man;alert(man.aboutMe());

也是比较简单,只是增加了一个新的属性,值是一个function。说到这,不知道你是否发现,在所有的定义或者赋值操作中,都是通过字典的方式来完成的,比如extend Backbone的Model,以及定义方法,定义默认值。方法的调用和其他的语言一样,直接 即可,参数的定义和传递也一样。2.4 监听对象中属性的变化

假设你有在对象的某个属性发生变化时去处理一些业务的话,下面的示例会有帮助。依然是定义那个类,不同的是我们在构造函数中绑定了name属性的change事件。这样当name发生变化时,就会触发这个function。var Man = Backbone.Model.extend({ initialize: function(){ alert('Hey, you create me!'); //初始化时绑定监听 this.bind("change:name",function(){ var name = this.get("name"); alert("你改变了name属性为:" + name); }); }, defaults: { name:'张三', age: '38' }, aboutMe: function(){ return '我叫' + this.get('name') + ',今年' + this.get('age') + '岁'; }});var man =new Man;//触发绑定的change事件,alert。man.set({name:'the5fire.com'})//触发绑定的change事件,alert。man.set({name:'the5fire.com'})2.5 为对象添加验证规则,以及错误提示var Man = Backbone.Model.extend({ initialize: function(){ alert('Hey, you create me!'); //初始化时绑定监听, change事件会先于validate发生 this.bind("change:name",function(){ var name = this.get("name"); alert("你改变了name属性为:" + name); }); this.bind("invalid",function(model,error){ alert(error); }); }, defaults: { name:'张三', age: '38' }, validate:function(attributes){ if(attributes.name == '') { return "name不能为空!"; } }, aboutMe: function(){ return '我叫' + this.get('name') + ',今年' + this.get('age') + '岁'; }});var man = new Man;// 这种方式添加错误处理也行// man.on('invalid', function(model, error){// alert(error);// });//默认set时不进行验证man.set({name:''});//手动触发验证, set时会触发//man.set({name:''}, {'valida te':true});//save时触发验证。根据验证规则,弹出错误提示。man.save(); 2.6 和服务器进行交互,对象的保存和获取

首先需要声明的是,这个例子需要后端配合,可以在code 目录中找到对应的py文件,需要webpy和mako这两个库。 这里需要为对象定义一个url属性,调用save方法时会post对象的所有属性到server端,调用fetch方法是又会发送get请求到server端。接受数据和发送数据均为json格式:var Man = Backbone.Model.extend({ url:'/man/', initialize: function(){ alert('Hey, you create me!'); //初始化时绑定监听 this.bind("change:name",function(){ var name = this.get("name"); alert("你改变了name属性为:" + name); }); this.bind("error",function(model,error){ alert(error); }); }, defaults: { name:'张三', age: '38' }, validate:function(attributes){ if(attributes.name == '') { return "name不能为空!"; } }, aboutMe: function(){ return '我叫' + this.get('name') + ',今年' + this.get('age') + '岁'; }});var man = new Man;;man.set({name:'the5fire'});man.save();//会发送POST到模型对应的url,数据格式为json{"name":"the5fire","age":38}//然后接着就是从服务器端获取数据使用方法fetch([options])var man1 = new Man;//第一种情况,如果直接使用fetch方法,那么他会发送get请求到你model的url中,//你在服务器端可以通过判断是get还是post来进行对应的操作。man1.fetch();//第二种情况,在fetch中加入参数,如下:man1.fetch({url:'/man/'});//这样,就会发送get请求到/getmans/这个url中,//服务器返回的结果样式应该是对应的json格式数据,同save时POST过去的格式。//不过接受服务器端返回的数据方法是这样的:man1.fetch({url:'/man/', success:function(model,response){ alert('success'); //model为获取到的数据 alert(model.get('name')); },error:function(){ //当返回格式不正确或者是非json数据时,会执行此方法 alert('error'); }});

还有一点值得一提的是关于url和urlRoot的事情了,如果你设置了url,那么你的CRUD都会发送对应请求到这个url上,但是这样有一个问题,就是delete请求,发送了请求,但是却没有发送任何数据,那么你在服务器端就不知道应该删除哪个对象(记录),所以这里又一个urlRoot的概念,你设置了urlRoot之后,你发送PUT和DELETE请求的时候,其请求的url地址就是:/baseurl/[model.id],这样你就可以在服务器端通过对url后面值的提取更新或者删除对应的对象(记录)。

补充一点,就是关于服务器的异步操作都是通过Backbone.sync这个方法来完成的,调用这个方法的时候会自动的传递一个参数过去,根据参数向服务器端发送对应的请求。比如你save,backbone会判断你的这个对象是不是新的,如果是新创建的则参数为create,如果是已存在的对象只是进行了改变,那么参数就为update,如果你调用fetch方法,那参数就是read,如果是destory,那么参数就是delete。也就是所谓的CRUD ("create", "read", "update", or "delete"),而这四种参数对应的请求类型为POST,GET,PUT,DELETE。你可以在服务器根据这个request类型,来做出相应的CRUD操作。

关于Backbone.sync在后面会有如何自定义这一部分的章节。

上面服务器端的代码在 code 下可以找到,基于webpy和mako的。第3章 Backbonejs中的Collections实践

上一章介绍了model的使用,model算是对现实中某一物体的抽象,比如你可以定义一本书的model,具有书名(title)还有书页(page_num)等属性。仅仅用一个Model是不足以呈现现实世界的内容,因此基于Model,这节我们来看collection。collection是model对象的一个有序的集合,也可以理解为是model的容器。概念理解起来十分简单,下面再通过几个例子来看一下,会觉得更容易理解。3.1 关于book和bookshelf的例子var Book = Backbone.Model.extend({ defaults : { title:'default' }, initialize: function(){ //alert('Hey, you create me!'); }});var BookShelf = Backbone.Collection.extend({ model : Book});var book1 = new Book({title : 'book1'});varbook2 = newBook({title : 'book2'});var book3 = new Book({title : 'book3'});//注意这里面是数组,或者使用add//var bookShelf = new BookShelf([book1, book2, book3]);var bookShelf = new BookShelf;bookShelf.add(book1);bookShelf.add(book2);bookShelf.add(book3);bookShelf.remove(book3);//基于underscore这个js库,还可以使用each的方法获取collection中的数据bookShelf.each(function(book){ alert(book.get('title'));});

很容易理解吧。3.2 使用fetch从服务器端获取数据

首先要在上面的的Bookshelf中定义url,注意collection中并没有urlRoot这个属性。或者直接在fetch方法中定义url的值,如下://注意这里bookShelf.url = '/books/';bookShelf.fetch({ success:function(collection, response, options){ collection.each(function(book){ alert(book.get('title')); }); },error:function(collection, response, options){ alert('error'); }});

其中也定义了两个接受返回值的方法,具体含义我想很容易理解,返回正确格式(json)的数据,就会调用success方法,错误格式的数据就会调用error方法,当然error方法也看添加和success方法一样的形参。

对应的BookShelf的返回格式如下:[{'title':'book0'},{'title':'book1'}.....]3.3 reset方法

这个方法的时候是要和上面的fetch进行配合的,collection在fetch到数据之后,默认情况会调用set方法(set方法会触发collection的add方法),但是可以通过参数{reset: true}来手动触发reset。这时你就需要在collection中定义reset方法或者是绑定reset方法。这里使用绑定演示:var showAllBooks = function(){ bookShelf.each(function(book){ //将book数据渲染到页面的操作。 document.writeln(book.get('title')); });}bookShelf.bind('reset',showAllBooks);bookShelf.url = '/books/';//注意这里bookShelf.fetch({ // 需要主动传递reset,才会触发reset reset: true, success:function(collection, response, options){ collection.each(function(book){ alert(book.get('title')); }); },error:function(collection, response, options){ alert('error'); }});

绑定的步骤要在fetch之前进行。3.4 发送数据到Server端

创建数据,其实就是调用collection的create方法,POST对应的Model对象(json数据)到配置好的url上。之后会返回一个model的实例,如下面代码中的onebook。var NewBooks = Backbone.Collection.extend({ model: Book, url: '/books/'});var books = new NewBooks;var onebook = books.create({ title: "I'm coming",});

完整代码可以在code 中找到, 服务器端的代码后面会介绍。第4章 Backbonejs中的Router实践

前面介绍了Model和Collection,基本上属于程序中静态的数据部分。这一节介绍将Backbone中的router,属于动态的部分,见名知意,router——路由的意思,显然是能够控制url指向哪个函数的。具体是怎么做的下面通过几个实例来看看。

在现在的单页应用中,所有的操作和内容都在一个页面上呈现,这意味着浏览器的url始终要定位到当前页面。那么一个页面中的左右的操作总不能都通过事件监听来完成,尤其是对于需要切换页面的场景以及需要分享、收藏固定链接的情况。因此就有了router,通过hash的方式(即#page)来完成。不过随着浏览器发展,大多数的浏览器已经可以通过history api来操控url的改变,可以直接使用 /page 来完成之前需要hash来完成的操作,这种方式看起来更为直观一些。下面通过几个Demo来切实体会一番。4.1 一个简单的例子var AppRouter = Backbone.Router.extend({ routes: { "*actions" : "defaultRoute" }, defaultRoute : function(actions){ alert(actions); }});var app_router = new AppRouter;Backbone.history.start();

需要通过调用Backbone.history.start()方法来初始化这个Router。

在页面上需要有这样的a标签:testActions

单击该链接时,便会触发defaultRouter这个方法。4.2 这个routes映射要怎么传参数

看下面例子,立马你就知道了。var AppRouter = Backbone.Router.extend({ routes: { "posts/:id" : "getPost", "*actions" : "defaultRoute" }, getPost: function(id) { alert(id); }, defaultRoute : function(actions){ alert(actions); }});var app_router =new AppRouter;Backbone.history.start();

对应的页面上应该有一个超链接:Post 120

从上面已经可以看到匹配#标签之后内容的方法,有两种:一种是用“:”来把#后面的对应的位置作为参数;还有一种是“*”,它可以匹配所有的url,下面再来演练一下。var AppRouter = Backbone.Router.extend({ routes: { "posts/:id" : "getPost", //下面对应的链接为download gif "download/*path": "downloadFile", //下面对应的链接为Load Route/Action View ":route/:action": "loadView", "*actions" : "defaultRoute" }, getPost: function(id) { alert(id); }, defaultRoute : function(actions){ alert(actions); }, downloadFile: function( path ){ alert(path);// user/images/hey.gif }, loadView: function( route, action ){ alert(route + "_" + action);// dashboard_graph }});var app_router = new AppRouter;Backbone.history.start();4.3 手动触发router

上面的例子都是通过页面单击触发router到对应的方法上,在实际的使用中,还存在一种场景就是需要在某一个逻辑中触发某一个事件,就像是jQuery中得trigger一样,下面的代码展示怎么手动触发router。routes: { "posts/:id" : "getPost", "manual": "manual", "*actions": "defaultRoute",},// 省略部分代码loadView: function( route, action ){ alert(route + "_" + action);// dashboard_graph},manual: function() { alert("call manual"); app_router.navigate("/posts/" + 404, {trigger: true, replace: true});}

对应着在页面添加一个a标签: manual 然后单击这个链接,便会触发posts/:id对应的方法。

这里需要解释的是navigate后面的两个参数。trigger表示触发事件,如果为false,则只是url变化,并不会触发事件,replace表示url替换,而不是前进到这个url,意味着启用该参数,浏览器的history不会记录这个变动。

完整代码依然在 code 中可以找到。第5章 Backbonejs中的View实践

前面介绍了存放数据的Model和Collection以及对用户行为进行路由分发的Router(针对链接)。这一章终于可以往页面上放点东西来玩玩了,将介绍Backbone中得View这个模块。Backbone的View是用来显示model中的数据到页面的,同时它也可用来监听DOM上的事件然后做出响应。但是这里要提一句的是,相比于Angularjs中model变化之后页面数据自动变化的特性,Backbone要手动来处理。至于这两种方式的对比,各有优劣,可以暂时不关心。

下面依然是通过几个示例来介绍下view的功能,首先给出页面的基本模板: the5fire-backbone-view

5.1 一个简单的viewvar SearchView = Backbone.View.extend({ initialize: function(){ alert('init a SearchView'); } });var searchView =new SearchView();

是不是觉得很没有技术含量,所有的模块定义都一样。5.2 el属性

这个属性用来引用DOM中的某个元素,每一个Backbone的view都会有这么个属性,如果没有显示声明,Backbone会默认的构造一个,表示一个空的div元素。el标签可以在定义view的时候在属性中声明,也可以在实例化view的时候通过参数传递。var SearchView = Backbone.View.extend({ initialize: function(){ alert('init a SearchView'); }});var searchView = newSearchView({el: $("#search_container")});

这段代码简单的演示了在实例化的时候传递el属性给View。下面我们来看看模板的渲染。var SearchView = Backbone.View.extend({ initialize: function(){ }, render: function(context) { //使用underscore这个库,来编译模板 var template = _.template($("#search_template").html()); //加载模板到对应的el属性中 $(this.el).html(template(context)); }});var searchView = new SearchView({el: $("#search_container")});//这个reander的方法可以放到view的构造函数中,这样初始化时就会自动渲染searchView.render({search_label: "搜索渲染"});

运行页面之后,会发现script模板中的html代码已经添加到了我们定义的div中。

这里面需要注意的是在模板中定义的所有变量必须在render的时候传递参数过去,不然就会报错。 关于el还有一个东西叫做$el,这个东西是对view中元素的缓存。5.3 再来看view中event的使用

页面上的操作除了可以由之前的router来处理之外,在一个view中定义元素,还可以使用event来进行事件绑定。这里要注意的是在view中定义的dom元素是指el标签所定义的那一部分dom节点,event进行事件绑定时会在该节点范围内查找。

来,继续看代码。var SearchView = Backbone.View.extend({ el: "#search_container", initialize: function(){ this.render({search_label: "搜索按钮"}); }, render: function(context) { //使用underscore这个库,来编译模板 var template = _.template($("#search_template").html()); //加载模板到对应的el属性中 $(this.el).html(template(context)); }, events:{ //就是在这里绑定的 //定义类型为button的input标签的点击事件,触发函数doSearch 'click input[type=button]' : 'doSearch' }, doSearch:function(event){ alert("search for " + $("#search_input").val()); }});var searchView = new SearchView();

自己运行下,是不是比写$("input[type=button]").bind('click',function(){})好看多了。5.4 View中的模板

上面已经简单的演示了模板的用法,如果你用过django模板的话,你会发现模板差不多都是那么回事。上面只是简单的单个变量的渲染,那么逻辑部分怎么处理呢,下面来看下。

把最开始定义的模板中的内容换成下面这个。

下面是js代码:var SearchView = Backbone.View.extend({ el: "#search_container", initialize:function(){ var labels = ['label1', 'label2', 'label3']; this.render({labels: labels}); }, render: function(context) { //使用underscore这个库,来编译模板 var template = _.template($("#search_template").html()); //加载模板到对应的el属性中 $(this.el).html(template(context)); },});var searchView = new SearchView();

再次运行,有木有觉得还不错,模板中使用的就基本的js语法。

总结一下,关于view中的东西就介绍这么多,文档上还有几个其他的属性,不过大体用法都一致。在以后的实践中用到在介绍。第6章 实战演练:todos分析(一)

经过前面几章的学习,Backbone中的Model,、Collection、Router、View,都简单地进行了介绍。下面,差不多就能开始使用Backbone来做东西了,所有的项目无外乎对这几个模块的使用。不过对于实际项目经验少些的同学,要拿起来用估计会有些麻烦。因此这里就先找个现成的案例分析一下。6.1 大家都来分析todos

关于Backbonejs实例分析的文章网上真是一搜一大把,之所以这么多,第一是这东西需求简单,不用花时间到理解情景中;第二是代码就是官方的案例,顺手可得,也省得去找了,自己琢磨一个不得花时间嘛。

于是就有人问了,你们都在分析todos,能不能有点新意呢。这问题要我说,如果你真的能把todos搞明白了,那其他的也就不用去看了。不管是看谁的分析,把这个搞明白的。所有的项目大体思路都差不多。尤其是对于这样的MVC的模型,就是往对应的模块里填东西。因此,不管有多少人都在分析这玩意,自己弄懂了才是应该关心的。

话虽如此,不同于网络上绝大部分的分析,the5fire除了分析这个,还是对其进行了扩充,另外在后面也会有真实的案例。但我也是从这些案例的代码中汲取的营养。

补充一下,新版的todos代码相较于之前简直清晰太多,完全可以当做一个前端的范本来学习、模仿。6.2 获取代码

todos的代码这里下载:https://github.com/jashkenas/backbone/,建议自己clone一份到本地。线上的地址是:http://backbonejs.org/examples/todos/index.html。

clone下来之后可以在example中找到todos文件夹,文件结构如下:examples├── backbone.localStorage.js└── todos ├── destroy.png ├── index.html ├── todos.css └── todos.js1 directory, 5 files

用浏览器打开index.html文件,推荐使用chome浏览器,就可以看到和官网一样的界面了。关键代码都在todos.js这个文件里。6.3 功能分析

首先来分析下页面上有哪些功能。

从这个界面我们可以总结出来,下面这些功能:* 任务管理 添加任务 修改任务 删除任务* 统计 任务总计 已完成数目

总体上就这几个功能。

这个项目仅仅是在web端运行的,没有服务器进行支持,因此在项目中使用了一个叫做backbone-localstorage的js库,用来把数据存储到前端。6.4 从模型下手

因为Backbone为MVC模式,根据对这种模式的使用经验,我们从模型开始分析。首先我们来看Model部分的代码:/****基本的Todo模型,属性为:title,order,done。***/var Todo = Backbone.Model.extend({ // 设置默认的属性 defaults: { title: "empty todo...", order: Todos.nextOrder(), done: false }, // 设置任务完成状态 toggle: function() { this.save({done: !this.get("done")}); }});

这段代码是很好理解的,不过我依然是画蛇添足的加上了一些注释。这个Todo显然就是对应页面上的每一个任务条目。那么显然应该有一个collection来统治(管理)所有的任务,所以再来看collection:/****Todo的一个集合,数据通过localStorage存储在本地。***/var TodoList = Backbone.Collection.extend({

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载