我们为什么需要Backbone.js
当我们创建单页web应用或者复杂的用户界面时,如果是简单的使用jQuery或者Mootools的话将会非常困难。问题在于标准的JavaScript库只是对于它们所擅长的领域很有用,以及你可能并没有意识到你需要一些结构化的东西来创建整个应用。最终的结果很可能是你的应用嵌套着一堆乱七八糟的jQuery回调函数,JS代码和DOM元素之间的耦合很严重。
我想我不需要在这里解释没有任何结构来创建应用是一个多么坏的想法。当然你总是可以发明你自己的结构化方法来创建应用但是你可能会因此而错过一些开源社区所带来的好东西。
为什么单页应用是未来的趋势
Backbone.js强调前端和服务器的交流应该完全通过一个RESTful API。web的发展趋势是所有的数据/内容都通过一个API暴露出来。这是因为浏览器不再是唯一的客户端,我们现在还有移动设备,平板电脑,Google眼镜以及智能冰箱等等。
Backbone.js怎么发挥作用
Backbone是一个非常小巧的库,它提供了大量的功能和结构。它对于客户端来说完全是MVC架构的,并且允许你将你的代码模块化。如果你阅读过一些入门教程那么你很快就能意识到使用Backbone的优势所在,这些都来源于Backbone轻量级的特性,你可以将它包含到现在或者未来的项目中。
其他的框架
如果你正在为你的单页web应用寻找一个框架,可以看看下面的这些链接:
- [A feature comparison of different fronted frameworks][2]
- [Todo MVC - Todo list implemented in the many different types of fronted frameworks][3]
什么是一个视图?
Backbone的视图被用来反映你应用中的数据模型是什么样的。它们也被用来监听事件并提供相应的响应。本文不会阐述如何将模型和几何绑定到视图,而是将做言语视图的功能以及如何连同一个JavaScript模板库一起使用视图,尤其是Underscore的__.template模板。
我们将使用jQuery 1.8.2作为我们的DOM操作器。你也可以使用其他的库例如Mootools或者Sizzle(现在还流行用zepto),但是官方的Backbone.js文档推荐使用jQuery。Backbone.View事件可能不会和jQuery意外的库协同工作。
为了证明视图的作用,我们将视线一个搜索框。实际的例子放在jsFiddle(http://jsfiddle.net/tBS4X/1/)上:
SearchView = Backbone.View.extend({
initialize: function(){
alert("Alerts sucks.");
}
});
//这个initialize函数总是在初始化一个Backbone视图的时候被调用
//把它当做是一个类的构造函数
var search_view = new SearchView();
“el”属性
“el”属性引用的是浏览器中创建的DOM对象。媒体个Backbone.js视图都有一个”el”属性,如果它没有被定义,Backbone.js会为你自动创建一个空的div元素。
我们现在来把我们的视图的”el”元素设置为div#search_container,这样依赖实际上是将Backbone.View作为了DOM元素的容器。
<div id="search_container"></div>
<script type="text/javascript">
searchView = Backbone.View.extend({
initialize: function(){
alert("Alert suck.");
}
});
var search_view = new searchView({el : $("#search_container")});
</script>
注意:记住这样的做法绑定了容器元素。任何我们触发的事件必须在这个元素中。
载入一个模板
Backbone.js依赖于Underscore.js,后者包含它自己的模板解决方案。如果需要获取更多的信息,请自己查看Underscore.js的文档。
我们来实现一个”render()”函数并且在视图完成初始化之后调用它。”render()”函数将使用jQuery把我们的模板载入到视图的”el”元素中。
<script type="text/template" id="search_template">
<label>Search</label>
<input type="text" id="search_input" />
<input type="button" id="search_button" value="Search" />
</script>
<div id="search_container"></div>
<script type="text/javascript">
searchView = Backbone.View.extend({
initialize: function(){
this.render();
},
render(){
//使用underscore编译模板
var template = __.template($("#search_template").html,{});
//将编译好的HTML载入到Backbone的"el"中
this.$el.html(template);
}
});
var search_view = new SearchView({ el : $("search_container")});
</script>
提示:将你的所有模板放到一个文件中然后从一个CDN获取它们。这确保了你的用户总是可以使用你的应用的缓存。
监听事件
为了绑定一个监听器到我们的视图,我们使用Backbone.View中的”event”属性。记住事件监听器只能绑定到”el”属性的子元素上。我们现在来给按钮绑定一个”click”事件。
<script type="text/template" id="search_template">
<label>Search</label>
<input type="text" id="search_input" />
<input type="button" id="search_button" value="Search" />
</script>
<div id="search_container"></div>
<script type="text/javascript">
SearchView = Backbone.View.extend({
initialize: function(){
this.render();
},
render: function(){
var template = __.template($("#search_template").html(),{});
this.$el.html(template);
},
events: {
"click input[type=button]": "doSearch";
},
doSearch: function(){
//按钮被点击时,你可以通过event.currentTarget获取被点击的元素
alert("Search for " + $("#search_input").val());
}
});
var search_view = new SearchView({el : $("#search_container")});
</script>
提示和技巧
使用模板变量:
<script type="text/template" id="search_template">
<!--通过<%= %>获取模板变量-->
<label><%= search_label %></label>
<input type="text" id="search_input" />
<input type="button" id="search_button" value="Search" />
</script>
<div id="search_container"></div>
<script type="text/javascript">
searchView = Backbone.View.extend({
initialize: function(){
this.render();
},
render: function(){
//使用Underscore.js模板传递变量
var variables = {search_label: "My Search"};
//使用underscore编译模板
var template = __.template($("#search_template").html,variables);
//将编译好的HTML载入到Backbone的"el"属性中
this.$el.html(template);
},
events: {
"click input[type=button]": "doSearch"
},
doSearch: function(){
//按钮被点击时,你可以通过event.currentTarget获取被点击的元素
alert("Search for " + $("#search_input").val());
}
});
var search_view = new searchView({el: $("#search_container")});
</script>
?