Backbone.js 主干多路由器陷阱-子路由器处理程序

Backbone.js 主干多路由器陷阱-子路由器处理程序,backbone.js,Backbone.js,进入主干路由器陷阱。想象一下,我有两个主干路由器: 1) RootRouter—只有一条路由和唯一的职责—使用RequireJS加载子计算机并实例化它 var RootRouter = Backbone.Router.extend({ routes: { '*all': 'invokeSubModule' }, invokeSubModule: function(route, args) { require(['SubRouter'], f

进入主干路由器陷阱。想象一下,我有两个主干路由器:

1) RootRouter—只有一条路由和唯一的职责—使用RequireJS加载子计算机并实例化它

var RootRouter = Backbone.Router.extend({
    routes: {
        '*all': 'invokeSubModule'
    },
    invokeSubModule: function(route, args) {
        require(['SubRouter'], function(subRouter) {
            new subRouter()
        })
    }
});
2) 子程序-标准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并重写
Route
方法,以便在
Backbone.getHash()
与Route方法相同时调用处理程序

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的情况下管理路由器延迟加载,因为在本例中,不会触发第一个
路由。

我能够复制您需要的行为,而无需对主干路由的内部进行黑客攻击,但我必须在初始化过程中做一些事情

首先,我将创建主路由器,并使用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>

样品
var RootRouter=Backbone.Router.extend({
路线:{
“*全部”:“调用子模块”,
“重置”:“调用子模块”,
},
调用子模块:函数(路由,参数){
新的子程序();
},
导航:函数(){
主干。路由器。原型。导航。应用(这个,参数);
},
执行:函数(回调,参数){
log('executeroot');
主干.Router.prototype.execute.apply(这是参数);
console.log('current fragment'+Backbone.history.fragment);
}
});
var子计算机=主干网.Router.extend({
路线:{
“some/bar”:“doBar”,
“some/foo”:“doFoo”
},
导航:函数(){
主干。路由器。原型。导航。应用(这个,参数);
},
执行:函数(回调,参数){
log('executesub');
主干.Router.prototype.execute.apply(这是参数);
console.log('current fragment'+Backbone.history.fragment);
},
doBar:function(){
$('#content').html('').append('BAR

'); }, doFoo:function(){ $('#content').html('').append('FOO

'); } }); $(文档).ready(函数(){ var mainRouter=新根路由器(); Backbone.history.start({silent:true}); var fragment=Backbone.history.fragment; mainRouter.navigate(“#”,true); mainRouter.navigate(片段,true); $('a')。单击(函数(){ mainRouter.navigate($(this.attr('href')); }); });



您是否尝试订阅您的
RootRouter
route
事件,如下所示:
RootRouter.on(“route:invokeSubModule”,function(url){subcomputer.navigate(url);})
?它不起作用,因为
navigate
不会触发回调,因为片段仍然相同。当前的解决方案是可行的,但我不确定它是否有新的想法,也不确定它是否是新发明的自行车,但这种方法也会迫使我在每个模块加载时重置历史记录?不,你不必在每个模块加载时重置,我只需在document ready事件中导航到重置路径,因此,我确信在加载子视图之前加载了子路由器,您可以检查片段变量以获得正确的子路由器加载EDI将用完整代码更新答案供您测试谢谢,明白您的想法,接受作为替代解决方案。