我正在将基于Backbone.js和jQuery的单页Web应用程序迁移到Chrome扩展程序。但是,pushState
和基于hashbang的路由器模式似乎都不能很好地适应扩展中的环境。我得出的结论是,我最好只是直接渲染用户交互视图,完全绕过window.location
系统。但是,我不太确定如何在不更改数十个文件中Router.navigate
的调用的情况下实现此目的。
是否有可插拔/模块化方式来保留Backbone路由系统但绕过对网址的任何更改?
答案 0 :(得分:22)
我真的很想坚持使用Router.navigate
从Backbone.js提供的路由系统中受益,而不必在Chrome扩展中使用时处理hashbang错误(例如包含斜线被覆盖的路由),你可以让Router.navigate
直接加载网址,跳过整个pushState体操。
这实际上很容易实现:
Router = Backbone.Router.extend({
navigate: function (url) {
// Override pushstate and load url directly
Backbone.history.loadUrl(url);
},
// Put routes here
routes: { }
});
然后,您可以在不更改历史记录的情况下调用Router.navigate(url)
加载新路由,甚至可以将操作绑定到包含data-backbone
属性(例如<a href="login" data-backbone>Login</a>
)的每个链接以及此类事件:
$(function(){
// Initialize router
Router = new Router;
Backbone.history.start();
// Bind a[data-backbone] to router
$(document).on('click', 'a[data-backbone]', function(e){
e.preventDefault();
Router.navigate( $(this).attr('href') );
});
});
答案 1 :(得分:2)
您可以重新定义Router.navigate
的功能,但最好不要完全使用Background.router。我认为这可能会造成一些混乱,如果您目前正在从视图中触发历史记录更改,那么如果没有它,您的代码将更加清晰。
Backbone.Marionette有一个控制器的概念,它的工作方式很像没有URL映射的路由器(使用Marionette,其目的是保持路由定义最小化,并为行为调用控制器)。您也不需要使用您不想要的任何Marionette组件。
如果你真的想坚持使用路由器,你可能只需将Backbone.History.navigate
重新定义为(注意,未经测试)
navigate: function(fragment, options) {
if (!History.started) return false;
if (!options || options === true) options = {trigger: options};
fragment = this.getFragment(fragment || '');
if (this.fragment === fragment) return;
this.fragment = fragment;
if (options.trigger) this.loadUrl(fragment);
}