陷入了 Backbone 路由器的陷阱。想象一下,我有 2 个 Backbone 路由器:
1) RootRouter - 只有一个路由和唯一的责任 - 使用 RequireJS 加载 subRouters 并实例化它。
var RootRouter = Backbone.Router.extend({
routes: {
'*all': 'invokeSubModule'
},
invokeSubModule: function(route, args) {
require(['SubRouter'], function(subRouter) {
new subRouter()
})
}
});
2) SubRouter - 标准 BB 路由器,带有路由哈希和处理程序。
var SubRouter = Backbone.Router.extend({
routes: {
'some/bar': 'doBar',
'some/foo': 'doFoo'
},
doBar: function() { ... },
doFoo: function() { ... }
});
我从 some/bar
URL 启动应用程序。
启动 RootRouter
实例化和 Backbone.History
启动。
正如预期的 RootRouter
- 匹配任何 URL 并触发 invokeSubModule
- 异步加载和 SubRouter
实例按预期工作,但问题与 相关some/bar
SubRouter
处理程序不会触发,因为页面 URL 与上一个 route
相比没有更改。
在寻找解决方案时,我只找到了在历史记录开始之前加载子路由器的情况的答案,但在我的情况下没有用。
经过一番挖掘,我找到了解决方案 - 扩展 Backbone.Route 并覆盖 route
方法,以便在 Backbone.getHash()
相等时调用处理程序到操作的路线方法。
Backbone.Router.extend({
route: function(route, name, callback) {
...
if (!callback) callback = this[name];
/* run handler immediately if route we add is the current URL fragment */
if(routeRegexp.test(Backbone.history.getHash()) ) {
this.execute(callback, this._extractParameters(routeRegexp, routeStr));
}
Backbone.history.route(route, function(fragment) {
....
});
return this;
}
})
所以我很困惑,这只是一个黑客行为,可能会在未来导致可能的错误。 因此,寻找如何解决此类问题的最佳实践并对我的解决方案提出批评。
还期望尽可能回答如何在没有 RootRouter 的情况下管理路由器延迟加载,因为在这种情况下,第一个 route
将不会被触发。
最佳答案
我能够复制您需要的行为,而无需破坏 Backbone 路由的内部结构,但我必须在初始化中做一些事情。
首先我将创建主路由器并使用silent option = true启动主干历史记录
var mainRouter = new RootRouter();
Backbone.history.start({silent: true});
这将启动主干历史记录,但不会路由当前 URL。 然后我获取当前片段并将其保存以供以后使用,然后导航到基本 url,然后返回到原始片段
var fragment = Backbone.history.fragment;
mainRouter.navigate('reset',true);
mainRouter.navigate(fragment, true);
这种方法的缺点是您需要在启动时执行 2 个路由
更新:
低于完整示例
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title> sample </title>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="http://underscorejs.org/underscore-min.js"></script>
<script type="text/javascript" src="http://backbonejs.org/backbone-min.js"></script>
<style type="text/css">
</style>
<script>
var RootRouter = Backbone.Router.extend({
routes: {
'*all': 'invokeSubModule',
'reset': 'invokeSubModule',
},
invokeSubModule: function(route, args) {
new SubRouter();
},
navigate: function () {
Backbone.Router.prototype.navigate.apply(this, arguments);
},
execute: function(callback, args) {
console.log('execute root');
Backbone.Router.prototype.execute.apply(this, arguments);
console.log ('current fragment ' + Backbone.history.fragment);
}
});
var SubRouter = Backbone.Router.extend({
routes: {
'some/bar': 'doBar',
'some/foo': 'doFoo'
},
navigate: function () {
Backbone.Router.prototype.navigate.apply(this, arguments);
},
execute: function(callback, args) {
console.log('execute sub');
Backbone.Router.prototype.execute.apply(this, arguments);
console.log ('current fragment ' + Backbone.history.fragment);
},
doBar: function() {
$('#content').html('').append('<p>BAR</p>');
},
doFoo: function() {
$('#content').html('').append('<p>FOO</p>');
}
});
$(document).ready(function(){
var mainRouter = new RootRouter();
Backbone.history.start({silent: true});
var fragment = Backbone.history.fragment;
mainRouter.navigate('#',true);
mainRouter.navigate(fragment, true);
$('a').click(function(){
mainRouter.navigate($(this).attr('href'));
});
});
</script>
</head>
<body>
<a id='home' href="#">home</a></br>
<a id='foo' href="#/some/foo">foo</a></br>
<a id='bar' href="#/some/bar">bar</a></br>
<div id='content'>HOME</div>
</body></html>
关于backbone.js - 主干多路由器陷阱 - 子路由器处理程序未调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26422342/