是否可以仅使用路由器阻止backbone.js
中的路由执行?
我知道每个路由都有一个回调方法,我可以检查是否允许路由,我只是看不到如何根据我的viewmodel上的属性(canNavigate)阻止执行。
我也希望这可以在未指定为路由的url上工作(sammy.js
不能这样做,骨干可以这样做吗?)。例如:
打开路由#/contact
时,将调用viewmodel“contact
”上的活动方法。
从#/contact
导航到#/page1
,/page2
或google.com
等任何其他网址时
我希望调用联系人视图模型上的canNavigate方法。
如果返回false,则应阻止到URL的路由并显示一条消息(我不需要代码显示消息等,如果可能,只需要backbone.js代码)。
backbone.js
这可能吗?
如果没有,那么其他框架(自我们已经尝试过此之后的sammy.js
除外)可能会成功吗?
答案 0 :(得分:1)
如果您编写路由器扩展,可以使用每个框架。这个问题要花费的时间少得多。我不知道它是否支持骨干,我会检查代码。
这是您正在寻找的方法:
route: function(route, name, callback) {
if (!_.isRegExp(route)) route = this._routeToRegExp(route);
if (!callback) callback = this[name];
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;
},
如您所见,它只是运行回调,并且不会阻止任何内容。
您可以通过以下方式扩展它:
var RouteError(message) {
this.name = "RouteError";
this.message = (message || "");
}
RouteError.prototype = Error.prototype;
var MyRouter = function (){
Backbone.Router.apply(this, arguments);
};
MyRouter.prototype = Object.create(Backbone.Router.prototype);
MyRouter.prototype.constructor = MyRouter;
_.extend(MyRouter.prototype, {
route: function(route, name, callback) {
if (!_.isRegExp(route)) route = this._routeToRegExp(route);
if (!callback) callback = this[name];
Backbone.history.route(route, _.bind(function(fragment) {
var args = this._extractParameters(route, fragment);
try {
callback && callback.apply(this, args);
}
catch(e)
{
if (e instanceof RouteError)
return this;
else
throw e;
}
this.trigger.apply(this, ['route:' + name].concat(args));
Backbone.history.trigger('route', this, name, args);
}, this));
return this;
},
});
或者这样:
var loadUrl = Backbone.History.prototype.loadUrl;
Backbone.History.prototype.loadUrl = function (fragmentOverride){
try {
loadUrl.apply(this, arguments);
}
catch (e){
if (e instanceof RouteError)
return ;
else
throw e;
}
};
(我没有检查这些......)
所以我不认为Backbone本身支持这个......
答案 1 :(得分:1)
在Backbone中,我发现在路由之前/之后检查事物的唯一方法是扩展Router.route。感觉不太干净,因为你必须从源代码复制并编辑,但这是我找到的唯一方法。在Backbone默认代码(1.0.0)之下以及注释之间您需要的自定义代码:
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 custom code
callback = _.wrap(callback, _.bind(function(cb) {
console.log('before');
_.bind(cb, this)();
console.log('after');
}, this));
// finish 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
是您在使用路由器时所期望的那个。否则我得到一个“这是未定义的”错误。
现在,您可以在路线开始之前/之后挂钩支票。在受影响的路由器中,您可以加载视图并执行您需要的任何操作。