2014-10-17 121 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