0

是否可以仅使用路由器来阻止路由执行backbone.js

我知道每个路由都有一个回调方法,我可以在其中检查是否允许路由,我只是看不到如何根据视图模型上的属性(canNavigate)阻止执行。

我还希望这适用于未指定为路由的 url(sammy.js不能这样做,骨干可以这样做吗?)。例如:

#/contact打开路由时contact,会调用 viewmodel ' ' 上的 active 方法。当导航#/contact到任何其他 url#/page1时,/page2或者google.com 我希望调用联系人视图模型上的 canNavigate 方法。如果返回 false,则应阻止到 url 的路由并显示一条消息(我不需要显示消息等的代码,如果可能,只需使用主干.js 代码)。

这可能backbone.js吗?如果没有,哪个其他框架(除了sammy.js我们已经尝试过这个)可以解决问题?

4

2 回答 2

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_.bindthis也是您在使用路由器时所期望的。否则我得到一个“这是未定义的”错误。

现在您可以在您的路线触发之前/之后挂钩您的支票。在受影响的路由器中,您可以加载您的视图并执行您需要的任何操作。

于 2013-04-30T14:47:01.530 回答
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 中是原生支持的......

于 2013-01-09T10:39:11.467 回答