2014-10-17 123 views
2

陷入与骨干路由器的陷阱。想象一下,我有2个主干路由器:骨干多路由器陷阱 - 子路由器处理程序doesent调用

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/barSubRouter关联,处理程序未触发,因为页面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不会被解雇。

+0

你尝试订阅你这样的''RootRouter'事件route'如下:'RootRouter.on(“路线:invokeSubModule“,function(url){SubRouter.navigate(url); })'? – Dethariel 2014-10-24 10:07:44

+0

它不会工作,因为'浏览'不会触发回调,因为片段仍然是相同的。目前的解决方案的工作原理,但我不知道它是否打破骨干思想,而不是自行车发明了 – Evgeniy 2014-10-24 10:59:00

回答

2

我能够复制你所需要的行为而不会破坏骨干路由的内部结构,但是我必须在初始化时做一些事情。

首先,我将创建主路由器和骨干启动历史与静音选项=真

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路由高达

UPDATE:

全样本

<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> 
+0

但这种方法也会迫使我重置每个模块负载的历史? – Evgeniy 2014-10-27 07:25:21

+0

不,您不必在每个模块加载时重置,我只是导航到文档就绪事件的重置路由,所以我确信在加载子视图之前加载了子路由器,您可以检查片段变量得到正确的子路由器加载 – mfarouk 2014-10-27 08:14:01

+0

我将用完整的代码更新答案,供您测试 – mfarouk 2014-10-27 08:14:23