一、应用场景
监听浏览器地址栏URL的hash值(#后面的部分)的变化,用正则匹配出参数执行相应的JS方法。URL地址的hash部分充当业务逻辑的分发单位。
示例:
<!DOCTYPE html>
<html>
<head>
<title>the5fire-backbone-router</title>
</head>
<body>
<a href="#/posts/120">Post 120</a>
<a href="#/download/user/images/hey.gif">download gif</a>
<a href="#/dashboard/graph">Load Route/Action View</a>
</body>
<script src="http://backbonejs.org/test/vendor/jquery.js"></script>
<script src="http://backbonejs.org/test/vendor/underscore.js"></script>
<script src="http://documentcloud.github.com/backbone/backbone-min.js"></script>
<script>
(function ($) {
//Backbone中的router,见名知意,router有路由的意思,显然这里是要控制url的。
//Backbone.Router会把你连接中的#标签当做是url路径
//从上面已经可以看到匹配#标签之后内容的方法,有两种:
//一种是用“:”来把#后面的对应的位置作为参数;还有一种是“*”,它可以匹配所有的url,下面再来演练一下。
var AppRouter = Backbone.Router.extend({
routes: {
"posts/:id" : "getPost",
"download/*path": "downloadFile", //对应的链接为<a href="#/download/user/images/hey.gif">download gif</a>
":route/:action": "loadView", //对应的链接为<a href="#/dashboard/graph">Load Route/Action View</a>
"*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();
})(jQuery);
</script>
</html>
<html>
<head>
<title>the5fire-backbone-router</title>
</head>
<body>
<a href="#/posts/120">Post 120</a>
<a href="#/download/user/images/hey.gif">download gif</a>
<a href="#/dashboard/graph">Load Route/Action View</a>
</body>
<script src="http://backbonejs.org/test/vendor/jquery.js"></script>
<script src="http://backbonejs.org/test/vendor/underscore.js"></script>
<script src="http://documentcloud.github.com/backbone/backbone-min.js"></script>
<script>
(function ($) {
//Backbone中的router,见名知意,router有路由的意思,显然这里是要控制url的。
//Backbone.Router会把你连接中的#标签当做是url路径
//从上面已经可以看到匹配#标签之后内容的方法,有两种:
//一种是用“:”来把#后面的对应的位置作为参数;还有一种是“*”,它可以匹配所有的url,下面再来演练一下。
var AppRouter = Backbone.Router.extend({
routes: {
"posts/:id" : "getPost",
"download/*path": "downloadFile", //对应的链接为<a href="#/download/user/images/hey.gif">download gif</a>
":route/:action": "loadView", //对应的链接为<a href="#/dashboard/graph">Load Route/Action View</a>
"*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();
})(jQuery);
</script>
</html>
二、构造函数
构造函数交简单,唯一需要注意的是this._bindRoutes()
将你自定义的routes中的键值对传入方法this.route
可以大胆猜测,Backbone.history.route方法其实是将正则(键被转化成了正则表达式),正则对应的回调添加到一个数组中。当hash值变化时取当前的hash值循环数组找到与正则对应的回调并执行。这个回调就是我们自定义的routes对象的值:
看代码Backbone.history.route:
二、Router的核心问题是:如何监听URL hash值的变化?查看History.prototype上的start方法:
先判断浏览器是否原生支持事件:popsatte、hashchange,如果不支持则使用定时间setInterval循环执行方法:checkUrl,事件间隔interval为50毫秒。可见低版本的浏览器要实现Router的功能是有性能损耗的。如果你的应用需要兼容低版本的浏览器,慎用Router
三、checkUrl方法。
handler.callback就是我们调用Backbone.history.route方法添加到handlers数组中的对象的callback属性:
关于浏览器监听hash值变化的原生方法可戳这里: