Backbone学习笔记
前言
其实早在两周前就开始学习Backbone框架了,知识总是学了忘,所以说写技术博客实在是一个好习惯^^ 而且写博客可以不用像写文档那样一本正经,文字可以随性一些,这也更符合我的语言习惯(话说这两周一直在不停地、不停地写文档……)。话不多说,来梳理一下Backbone的学习心得吧。
学习资料:http://yujianshenbing.iteye.com/
(一)Get Started!
什么是Backbone?用我的话来说,就是基于MVC模式的前端框架。暑期小学期写网站用的是asp.net,它就基于MVC这种模式,所以我对它还是比较了解的。Backbone则是在javascript上实现了MVC框架的封装,这一点令我感到十分惊奇(毕竟见识少)。
Backbone框架有以下特性(好的方面):
(1)Backbone将原本零散的JS组织起来,划分为三个层次,彼此间耦合度较小。
(2)Backbone还是一种轻量级的框架(1000行左右),较小的规模带来较短的学习时间和快速上手。
(3)Backbone在数据方面完成了后端数据更改和前端显示的同步更新,在界面方面则提供了方便的事件管理机制。程序员要关心的事情更少了。
Backbone当然也有其不足。总的来看,Backbone确实提供了一个MVC框架,可是也就提供了一个MVC框架而已。Backbone并没有提供很多的api,很多事情依然要由程序员来操心。而且,Backbone还要求我们写很多的样板代码,这增加许多无意义的工作,大大降低了开发效率。鉴于我们下面还要具体谈谈这个框架,我在这里就不继续说它的坏话了。有兴趣的读者可以看一看:http://www.csdn.net/article/2013-04-25/2815032-A-Comparison-of-Angular-Backbone-CanJS-and-Ember
(二)View:视图类
View部分与视图、界面相关。Backbone不像asp.net的MVC框架那样,将View部分中直接绘制整个页面。Backbone的View更像是一般意义上的Controller,主要是对交互事件作出响应。先来看看定义View的方法:
<div title="列表" style="color:red" id="list" class="listview"></div> <script type="text/javascript"> var ListView = Backbone.View.extend({ el : '#list' }); var listview = new ListView(); </script>
首先定义ListView为View的一个继承,然后用el获取页面上的DOM元素'#list'。View提供了一个方便获取DOM元素的方法,就是el。一旦一个View获取了el,就相当于它“锁定”了页面上的某个DOM元素,之后的所有事件响应等都与这个DOM关联。
同时,View能够通过设定events将控件绑定:
<p id="view"> <input type="button" value="Create" id="create" /> <input type="button" value="Read" id="read" /> <input type="button" value="Update" id="update" /> <input type="button" value="Delete" id="delete" /> </p> <script type="text/javascript"> var MyView = Backbone.View.extend({ el : '#view', events : { 'click #create' : 'createData', 'click #read' : 'readData', 'click #update' : 'updateData', 'click #delete' : 'deleteData' }, createData : function() { // todo }, readData : function() { // todo }, updateData : function() { // todo }, deleteData : function() { // todo } }); var view = new MyView(); </script>
看了代码就会明白,View是如何处理页面交互事件的了:先在events中通过固定的格式:
events:{
'动作名_DOM元素':'响应函数'
}
如:
events : {
'click #create' : 'createData'
}
createData : function() {
// todo
},
来将针对DOM元素的某个事件绑定到某个函数中,再在后面对响应函数进行实现,就完成了一个事件响应控制。
当然,作为View(而不是Controller),它依然可以完成View本来该干的事:对页面进行渲染。通过绑定一个页面上已有的DOM,或者直接新建一个新的DOM元素(然后再将它append到页面里),之后就可以进行各种修改了。
(三)Model:数据模型
Model是Backbone中所有数据模型的基类,用于封装原始数据,并提供对数据进行操作的方法,我们一般通过继承的方式来扩展和使用它。它支持数据对象的创建、修改、删除等操作:
创建:defaults初始化,在创建实例对象时可以更改default值。
// 定义Book模型类 var Book = Backbone.Model.extend({ defaults : { name : 'unknown', author : 'unknown', price : 0 } }); // 实例化模型对象 var javabook = new Book({ name : 'Thinking in Java', author : 'Bruce Eckel', price : 395.70 });
修改:通常可以调用模型对象的set()方法,来修改模型中的数据。
javabook.set('price', 88.50);
删除:可以调用的方法有clear()、unset()。
//unset()方法可以删除对象name属性 javabook.unset('name'); //clear()方法会删除模型中的所有数据 javabook.clear();
Model还支持将模型数据同步到服务器:
模型对象提供了3个方法用于和服务器保持数据同步:
- save()方法:在服务器创建或修改数据
- fetch()方法:从服务器获取数据
- destroy()方法:从服务器移除数据
Model还能通过validate方法进行数据验证。当validate验证不通过时,会触发error事件,并将模型对象和validate方法的返回值传递给error事件的监听函数:
// 定义Book模型类 var Book = Backbone.Model.extend({ validate : function(data) { if(data.price < 1) { return '书籍价格不应低于1元.'; } } }); var javabook = new Book(); // 监听error事件,当验证失败时触发 javabook.on('error', function(model, error) { console.log(error); }); javabook.set('price', 0);
之前说过,Model能够与服务器进行数据同步。相关知识可以总结如下:
- 数据标识:每个模型对应唯一一个id,映射数据库中的一条数据。(由客户端新建的模型保存时不会在URL后加上id。)
- 访问服务器:默认使用PATHINFO方式访问服务器接口。
- 交互:Backbone支持3种URL配置方式,比较细,这里就不无脑copy了。请读者朋友查看教程原文相应部分。
(四)Collection:数据模型集合
我们上面已经简要介绍了一点Model和View的知识,值得一提的是,剩下的MVC的C,在Backbone中并不是Controller,而是Collection。
简单来说,Collection就是Model的集合,支持批量同步数据。这里不展开了。
(五)Router:路由
Backbone的MVC框架除了像Model的M、像Controller的V和不像Controller的C(这些说法有些奇怪),还有一个Router部分。它承担了原先属于Controller的另一功能:路由跳转。
Backbone的路由导航是由Backbone.Router和Backbone.History两个类共同完成的:
- Router类用于定义和解析路由规则,并将URL映射到Action。
- History类用于监听URL的变化,和触发Action方法。
这次我们直接把popush的Router部分作为例子拿来看看:
var PageRouter = Backbone.Router.extend({ routes: { 'login': function() { this.analy('login'); }, 'register': function() { this.analy('register'); }, 'index/*filepath': function(arg1) { this.analy('index', arg1); }, '/*filepath': function(arg1) { this.analy('index', arg1); }, 'edit/': function(arg1) { this.analy('edit'); }, }, //... analy: function(name) { //... }, initialize: function() { var pages = this.pages, j; for (var i in pages) { j = pages[i]; if (j.el) { j.el = $(j.el); j.shown = !(j.el.is(':hidden')); } } this.routeLock = false; } });
routes部分首先将一些路由与对应的事件进行绑定。比如当我们将浏览器地址栏的url改为http://localhost/login时,就会触发"login"对应的事件analy("login")。analy中对于login做了一些操作,上面省略了那些代码。大致来说就是从后台拿出数据到前台显示,并跳转页面。
需要注意的是,Backbone其实是基于SPA(Single Page Application)的机制,实际上只有一张网页,目的是为了给用户营造出无刷新的舒适体验。所以我们所说的“跳转页面”,实际上就是显示某个Container DOM,隐藏其他的Container DOM。analy函数完成了这些工作。
最后,routes还提供了initialize,它相当于一个构造函数,完成一些初始化工作。程序员需要调用下面这句话,开始router的运作:
Backbone.history.start();
(六)小结
总体来看,Backbone比较容易学习。然而,正如我们阅读Popush代码时感受到的,由于Backbone框架本身并没有很多工具可供使用,网站编写人员不得不使用了很多其他库和api做补充。Backbone是一个清晰的、结构化的框架,它就像网站前端的骨架,骨架搭好了,我们还得自己去寻找血和肉来完善它。
当然,关于Backbone,要学的还有很多!