因为最近的工作中使用到了backbone.js框架,所以在网上找了些资料,但是关于这个框架的中文资料实在是太少了,没有办法,只好自己翻译了壹篇简单的入门教材。如果翻译得不好,请大家口下留情。另外,大家也可以签出 Agility.js 的代码,它也是壹个用于替代Backbone.js的壹个简单框架。
这是壹个简单的 Backbone.js 教程,由不言自明的"Hello World"到日益复杂的例子组成,它的出现是为了提供壹个平滑的从零过渡到流行的 Todos样例 。教程开始于最小化的视图(View)对象,并且逐步的介绍事件绑定、事件处理、模型与集合。壹旦进入教程,可以使用右上角的导航菜单来查看其它例子。例子的序号按照其复杂程度递增。
下面的代码是基于HTML5的页面,最好使用最新版本的Firefox/Chrome/Opera/Safari浏览,不要用IE浏览器,你懂的。
01 |
<!DOCTYPE html> |
02 |
< html > |
03 |
< head > |
04 |
< meta charset = "utf-8" > |
05 |
< title >hello-backbonejs</ title > |
06 |
</ head > |
07 |
< body > |
08 |
< script src = "https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" ></ script > |
09 |
< script src = "http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js" ></ script > |
10 |
< script src = "http://ajax.cdnjs.com/ajax/libs/underscore.js/1.1.6/underscore-min.js" ></ script > |
11 |
< script src = "http://ajax.cdnjs.com/ajax/libs/backbone.js/0.3.3/backbone-min.js" ></ script > |
12 |
13 |
< script src = "...number.js..." type = "text/javascript" ></ script > |
14 |
</ body > |
15 |
</ html > |
1.js 本例说明最小化的视图的声明与实例化。效果演示看这里。
ListView类:是我们的主要的应用视图。
initialize():自动调用上述实例,你可以在这里做除了界面元素事件以外的所有类型的绑定,比如说单击事件等等。
render():用于渲染整个视图的函数。this.el:需要用户手动调用。
listView实例:实例化整个视图。
01 |
( function ($){ |
02 |
//自运行的闭包 |
03 |
var ListView = Backbone.View.extend({ |
04 |
el: $( 'body' ), // attaches `this.el` to an existing element. |
05 |
06 |
initialize: function (){ |
07 |
_.bindAll( this , 'render' ); // fixes loss of context for 'this' within methods |
08 |
|
09 |
this .render(); // not all views are self-rendering. This one is. |
10 |
}, |
11 |
12 |
render: function (){ |
13 |
$( this .el).append( "<ul> <li>hello world</li> </ul>" ); |
14 |
} |
15 |
}); |
16 |
17 |
var listView = new ListView(); |
18 |
})(jQuery); |
2.js 本例说明如何绑定DOM事件到视图的方法中。效果演示看这里。
events:DOM事件绑定到视图方法中,Backbone没有独立的控制器来处理这种绑定,它们全部发生在视图层中。
render():正在展示如何将壹个按钮来添加到新的list条目中。
addItem():通过上述点击事件自动触发的自定义的函数。
01 |
( function ($){ |
02 |
var ListView = Backbone.View.extend({ |
03 |
el: $( 'body' ), // el attaches to existing element |
04 |
05 |
events: { |
06 |
'click button#add' : 'addItem' |
07 |
}, |
08 |
initialize: function (){ |
09 |
_.bindAll( this , 'render' , 'addItem' ); // every function that uses 'this' as the current object should be in here |
10 |
|
11 |
this .counter = 0; // total number of items added thus far |
12 |
this .render(); |
13 |
}, |
14 |
15 |
render: function (){ |
16 |
$( this .el).append( "<button id='add'>Add list item</button>" ); |
17 |
$( this .el).append( "<ul></ul>" ); |
18 |
}, |
19 |
20 |
addItem: function (){ |
21 |
this .counter++; |
22 |
$( 'ul' , this .el).append( "<li>hello world" + this .counter+ "</li>" ); |
23 |
} |
24 |
}); |
25 |
26 |
var listView = new ListView(); |
27 |
})(jQuery); |
3.js 这个样例说明如何使用模型中的集合来存储数据,以及如何将数据的改变绑定到视图。演示效果看这里。
Item 类:模型层的原子(最小)部分。壹个模型是壹个基本的Javascript对象,例如:键值对,以及壹些用于事件响应、数据持久化的帮助函数等。
List 类:壹个条目的集合。基本上是壹些模型对象的数组和壹些帮助函数。
initialize() 正在实例化壹个集合,并且绑定它的添加事件到自己的方法 appendItem。(Backbone不在壹个单独的控制器中提供回调函数用于绑定)。
Save 参考这个以便它能够访问下面的callback范围内的数据。
addItem() 现在独立处理模型与视图。现在视图更新被授予下面的事件监听器 appendItem()。
appendItem() 被集合事件add触发,可视化的处理更新。
01 |
( function ($){ |
02 |
03 |
var Item = Backbone.Model.extend({ |
04 |
defaults: { |
05 |
part1: 'hello' , |
06 |
part2: 'world' |
07 |
} |
08 |
}); |
09 |
|
10 |
11 |
var List = Backbone.Collection.extend({ |
12 |
model: Item |
13 |
}); |
14 |
15 |
var ListView = Backbone.View.extend({ |
16 |
el: $( 'body' ), |
17 |
events: { |
18 |
'click button#add' : 'addItem' |
19 |
}, |
20 |
21 |
initialize: function (){ |
22 |
_.bindAll( this , 'render' , 'addItem' , 'appendItem' ); // remember: every function that uses 'this' as the current object should be in here |
23 |
|
24 |
this .collection = new List(); |
25 |
this .collection.bind( 'add' , this .appendItem); // collection event binder |
26 |
27 |
this .counter = 0; |
28 |
this .render(); |
29 |
}, |
30 |
render: function (){ |
31 |
32 |
var self = this ; |
33 |
$( this .el).append( "<button id='add'>Add list item</button>" ); |
34 |
$( this .el).append( "<ul></ul>" ); |
35 |
_( this .collection.models).each( function (item){ // in case collection is not empty |
36 |
self.appendItem(item); |
37 |
}, this ); |
38 |
}, |
39 |
40 |
addItem: function (){ |
41 |
this .counter++; |
42 |
var item = new Item(); |
43 |
item.set({ |
44 |
part2: item.get( 'part2' ) + this .counter // modify item defaults |
45 |
}); |
46 |
this .collection.add(item); // add item to collection; view is updated via event 'add' |
47 |
}, |
48 |
49 |
appendItem: function (item){ |
50 |
$( 'ul' , this .el).append( "<li>" +item.get( 'part1' )+ " " +item.get( 'part2' )+ "</li>" ); |
51 |
} |
52 |
}); |
53 |
54 |
var listView = new ListView(); |
55 |
})(jQuery); |
4.js 这个样例说明如何渲染模型到专门查看的视图。演示效果看这里。
ItemView 类:负责渲染每个独立的条目。
appendItem() 不再负责渲染独立的项目。它现在授予 render() 方法到每个独立的 ItemView 实例。
01 |
( function ($){ |
02 |
var Item = Backbone.Model.extend({ |
03 |
defaults: { |
04 |
part1: 'hello' , |
05 |
part2: 'world' |
06 |
} |
07 |
}); |
08 |
|
09 |
var List = Backbone.Collection.extend({ |
10 |
model: Item |
11 |
}); |
12 |
13 |
var ItemView = Backbone.View.extend({ |
14 |
tagName: 'li' , // name of (orphan) root tag in this.el |
15 |
initialize: function (){ |
16 |
_.bindAll( this , 'render' ); // every function that uses 'this' as the current object should be in here |
17 |
}, |
18 |
render: function (){ |
19 |
$( this .el).html( '<span>' + this .model.get( 'part1' )+ ' ' + this .model.get( 'part2' )+ '</span>' ); |
20 |
return this ; // for chainable calls, like .render().el |
21 |
} |
22 |
}); |
23 |
|
24 |
var ListView = Backbone.View.extend({ |
25 |
el: $( 'body' ), // el attaches to existing element |
26 |
events: { |
27 |
'click button#add' : 'addItem' |
28 |
}, |
29 |
initialize: function (){ |
30 |
_.bindAll( this , 'render' , 'addItem' , 'appendItem' ); // every function that uses 'this' as the current object should be in here |
31 |
|
32 |
this .collection = new List(); |
33 |
this .collection.bind( 'add' , this .appendItem); // collection event binder |
34 |
35 |
this .counter = 0; |
36 |
this .render(); |
37 |
}, |
38 |
render: function (){ |
39 |
var self = this ; |
40 |
$( this .el).append( "<button id='add'>Add list item</button>" ); |
41 |
$( this .el).append( "<ul></ul>" ); |
42 |
_( this .collection.models).each( function (item){ // in case collection is not empty |
43 |
self.appendItem(item); |
44 |
}, this ); |
45 |
}, |
46 |
addItem: function (){ |
47 |
this .counter++; |
48 |
var item = new Item(); |
49 |
item.set({ |
50 |
part2: item.get( 'part2' ) + this .counter // modify item defaults |
51 |
}); |
52 |
this .collection.add(item); |
53 |
}, |
54 |
55 |
appendItem: function (item){ |
56 |
var itemView = new ItemView({ |
57 |
model: item |
58 |
}); |
59 |
$( 'ul' , this .el).append(itemView.render().el); |
60 |
} |
61 |
}); |