4

我正在开发一个我的用户需要登录的应用程序,从这个意义上说,登录略有不同,因为用户没有按说注册。他们输入他们的名字和房间名称,然后他们连接。房间本身包含用户所需的所有设置,例如;

  • 房间名称
  • 查看设置 - 允许打开或关闭选项
  • ETC...

所以我想做的是连接到路由事件,所以/login如果用户没有登录,我可以强制用户转到根目录。

当然必须有一种 DRY 方式来做到这一点,而无需为每条路线添加条件?

4

4 回答 4

4

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 版本中添加的。

于 2014-12-30T20:18:46.903 回答
3

我想到的唯一选择是覆盖当前的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 原生的!

希望这可以帮助

于 2012-12-20T11:59:42.957 回答
2

我想扩展@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

于 2013-04-30T14:51:34.867 回答
1

在初始化应用程序的代码中:

// Initialize router(s)
Backbone.history.on("route", function() {
    if (!authenticated) Backbone.history.navigate("/login", true);
});
Backbone.history.start();
于 2012-12-20T14:40:05.570 回答