7

我试图在执行路由回调之前将路由重定向到另一个。我有以下代码:

console.log("file loaded");
(function (History) {
    var _navigate = History.prototype.navigate;

    _.extend(History.prototype, {
        navigate: function (fragment, opts) {
            alert("adad");
            return _navigate.call(this, fragment, opts);
        }
    });
})(Backbone.History);

此代码包装Backbone.History.navigate方法,并在方法调用时显示警报。但是当我改变路线时,这个警报永远不会出现。

console.log行只是为了确保在backbone.js 之后加载了该文件。

这段代码有什么问题?

4

1 回答 1

2

我认为你压倒了错误的事情:这navigate不是你认为的那样使用。

让我们看一部分Backbone.history.start

// Start the hash change handling, returning `true` if the current URL matches
// an existing route, and `false` otherwise.
start: function(options) {
  //...
  if (this._hasPushState) {
    Backbone.$(window).on('popstate', this.checkUrl);
  } else if (this._wantsHashChange && ('onhashchange' in window) && !oldIE) {
    Backbone.$(window).on('hashchange', this.checkUrl);
  } else if (this._wantsHashChange) {
    this._checkUrlInterval = setInterval(this.checkUrl, this.interval);
  }

您将看到在 Backbone 中处理路由的所有各种方式都经过checkUrl而不是navigate. 该checkUrl方法做了一些忙碌的工作和调用loadUrl;忙碌工作的一部分是这样的

  if (this.iframe) this.navigate(current);

sonavigate将被调用,但只有当 an<iframe>用于模拟hashchangepopstate事件时才会调用,而 AFAIK 仅在您使用旧版本的 IE 时才会发生。

回到通常的代码路径。我们已经看到它checkUrl做了一些繁忙的工作和电话loadUrl,那么它有什么作用呢?loadUrl这样做

loadUrl: function(fragmentOverride) {
  var fragment = this.fragment = this.getFragment(fragmentOverride);
  var matched = _.any(this.handlers, function(handler) {
    if (handler.route.test(fragment)) {
      handler.callback(fragment);
      return true;
    }
  });
  return matched;
}

如果您查看 in 中的route方法和 in 中Historyroute方法,Route您会发现这handler.callback是从您的一个路由器调用路由处理程序并触发路由事件的原因。

您要替换的navigate方法几乎仅由Router'snavigate使用:

navigate: function(fragment, options) {
  Backbone.history.navigate(fragment, options);
  return this;
}

如果你想在调用路由处理程序之前重定向,你可以loadUrl用这样的东西替换:

(function(History) {
    var _loadUrl = History.prototype.loadUrl;
    _.extend(History.prototype, {
        loadUrl: function() {
            var args = [].slice.apply(arguments);
            args[0] = this.getFragment(args[0]);
            // If args[0] is the fragment that you want to
            // redirect then replace it here or do whatever
            // needs to be done.
            return _loadUrl.apply(this, args);
        }
    });
})(Backbone.History);

演示:http: //jsfiddle.net/ambiguous/e4KYK/

总的来说,我认为你最好在普通路由处理程序中处理重定向:当调用有问题的路由时,只需调用navigate任何方便的路由器。


请记住,除了方法Backbone.History之外没有记录,因此这里的所有内容都可能发生变化。start

于 2013-02-13T07:58:11.077 回答