我正在开发一个我的用户需要登录的应用程序,从这个意义上说,登录略有不同,因为用户没有按说注册。他们输入他们的名字和房间名称,然后他们连接。房间本身包含用户所需的所有设置,例如;
- 房间名称
- 查看设置 - 允许打开或关闭选项
- ETC...
所以我想做的是连接到路由事件,所以/login
如果用户没有登录,我可以强制用户转到根目录。
当然必须有一种 DRY 方式来做到这一点,而无需为每条路线添加条件?
我正在开发一个我的用户需要登录的应用程序,从这个意义上说,登录略有不同,因为用户没有按说注册。他们输入他们的名字和房间名称,然后他们连接。房间本身包含用户所需的所有设置,例如;
所以我想做的是连接到路由事件,所以/login
如果用户没有登录,我可以强制用户转到根目录。
当然必须有一种 DRY 方式来做到这一点,而无需为每条路线添加条件?
Backbone 的路由器有一个execute
可以覆盖的方法。每次匹配路由时都会调用它,在调用回调之前:
var Router = Backbone.Router.extend({
execute: function(callback, args) {
// Do what you want here!
if (callback) callback.apply(this, args);
}
});
该方法是在 2014 年 2 月 13 日的 1.1.1 版本中添加的。
我想到的唯一选择是覆盖当前的Router.route
-function,目前它看起来像这样:
route: function(route, name, callback) {
if (!_.isRegExp(route)) route = this._routeToRegExp(route);
if (!callback) callback = this[name]; // this is of interest
Backbone.history.route(route, _.bind(function(fragment) {
var args = this._extractParameters(route, fragment);
callback && callback.apply(this, args);
this.trigger.apply(this, ['route:' + name].concat(args));
Backbone.history.trigger('route', this, name, args);
}, this));
return this;
},
您要做的是用一个函数包装每个回调,该函数检查是否满足您想要的条件,然后调用 wrappee 或重新路由以登录。Underscore 的wrap
-function在这里很有用。
route: function(route, name, callback) {
... // same as above
if (!callback) callback = this[name];
_.wrap(callback, function(cb) {
if (userIsLoggedIn()) {
cb();
} else {
this.navigate("url/to/login");
}
});
... // same as above
},
当然,您必须添加对实际登录路线的检查,以免造成无限循环!
编辑:
您不必修改源代码,最简单的方法是:
var CustomRouter = Router.extend({
route: function() {
// your overwrite here
}
});
在评论中使用它,因为它是 Backbone 原生的!
希望这可以帮助
我想扩展@jakee 的回答和@Joel Nation 的评论。this
我在受影响的路线上按预期工作时遇到了麻烦。我得到“这是未定义的”。在使其工作的最终代码下方:
Backbone.Router.prototype.route = function(route, name, callback) {
if (!_.isRegExp(route)) route = this._routeToRegExp(route);
if (_.isFunction(name)) {
callback = name;
name = '';
}
if (!callback) callback = this[name];
// here my custom code
callback = _.wrap(callback, _.bind(function(cb) {
if (name == 'login' || sessionModel.authenticated()) {
_.bind(cb, this)();
} else {
this.navigate('login', {trigger: true});
}
}, this));
// finish my custom code
var router = this;
Backbone.history.route(route, function(fragment) {
var args = router._extractParameters(route, fragment);
callback && callback.apply(router, args);
router.trigger.apply(router, ['route:' + name].concat(args));
router.trigger('route', name, args);
Backbone.history.trigger('route', router, name, args);
});
return this;
};
请注意_.wrap
,您所期望的也是_.bind
如此。this
在初始化应用程序的代码中:
// Initialize router(s)
Backbone.history.on("route", function() {
if (!authenticated) Backbone.history.navigate("/login", true);
});
Backbone.history.start();