Backbone.js:获取当前路由

时间:2011-09-27 03:37:56

标签: backbone.js

使用Backbone,我有可能获得当前路线的名称吗?我知道如何绑定到路由更改事件,但我希望能够在其他时间,在更改之间确定当前路由。

7 个答案:

答案 0 :(得分:207)

如果您已在应用程序中实例化路由器,则以下行返回当前片段:

Backbone.history.getFragment();

来自Backbone.js documentation

” [...] 历史记录充当全局路由器(每帧)来处理hashchange事件或pushState,匹配适当的路由,并触发回调。您不应该自己创建其中一个 - 如果您使用路由器,则应该使用将自动为您创建的Backbone.history的引用 路线。 [...]“

如果你需要绑定到该片段的函数的名称,你可以在你的路由器范围内做这样的事情:

alert( this.routes[Backbone.history.getFragment()] );

或者从路由器外面这样说:

alert( myRouter.routes[Backbone.history.getFragment()] );

答案 1 :(得分:55)

Robert's answer很有意思,但遗憾的是,只有当哈希完全按照路由中的定义时才会有效。例如,如果您有user(/:uid)的路由,如果Backbone.history.fragment"user""user/1"(两者都是两个最明显的用例),则不会匹配这样的路线)。换句话说,如果哈希值恰好是"user(/:uid)"(极不可能),它只能找到合适的回调名称。

由于我需要此功能,因此我使用Backbone.Router扩展了current - 函数,该函数重用了历史记录和路由器对象用于将当前片段与定义的路由匹配的一些代码,以触发相应的打回来。 对于我的用例,它采用可选参数route,如果设置为trueful将返回为路由定义的相应函数名称。否则它将从Backbone.History.fragment返回当前的哈希片段。

您可以将代码添加到现有的Extend,在其中初始化和设置Backbone路由器。

var Router = new Backbone.Router.extend({

    // Pretty basic stuff
    routes : {
        "home" : "home",
        "user(:/uid)" : "user",
        "test" : "completelyDifferent"
    },

    home : function() {
        // Home route
    },

    user : function(uid) {
        // User route
    },

    // Gets the current route callback function name
    // or current hash fragment
    current : function(route){
        if(route && Backbone.History.started) {
            var Router = this,
                // Get current fragment from Backbone.History
                fragment = Backbone.history.fragment,
                // Get current object of routes and convert to array-pairs
                routes = _.pairs(Router.routes);

            // Loop through array pairs and return
            // array on first truthful match.
            var matched = _.find(routes, function(handler) {
                var route = handler[0];

                // Convert the route to RegExp using the 
                // Backbone Router's internal convert
                // function (if it already isn't a RegExp)
                route = _.isRegExp(route) ? route :  Router._routeToRegExp(route);

                // Test the regexp against the current fragment
                return route.test(fragment);
            });

            // Returns callback name or false if 
            // no matches are found
            return matched ? matched[1] : false;
        } else {
            // Just return current hash fragment in History
            return Backbone.history.fragment
        }
    }
});

// Example uses:
// Location: /home
// console.log(Router.current()) // Outputs 'home'
// Location: /user/1
// console.log(Router.current(true)) // Outputs 'user'
// Location: /user/2
// console.log(Router.current()) // Outputs 'user/2'
// Location: /test
// console.log(Router.current(true)) // Outputs 'completelyDifferent'

我确信可以做一些改进,但这是让你入门的好方法。此外,在不扩展Route-object的情况下,可以轻松创建此功能。我这样做是因为这是我设置的最便捷方式。

我还没有完全测试过,所以如果有什么事情发生,请告诉我。


更新04/25/2013

我对函数做了一些更改,因此我不返回散列或路由回调名称,而是返回一个带有fragment,params和route的对象,这样你就可以访问当前路由中的所有数据了,就像你从路线事件。

您可以看到以下更改:

current : function() {
    var Router = this,
        fragment = Backbone.history.fragment,
        routes = _.pairs(Router.routes),
        route = null, params = null, matched;

    matched = _.find(routes, function(handler) {
        route = _.isRegExp(handler[0]) ? handler[0] : Router._routeToRegExp(handler[0]);
        return route.test(fragment);
    });

    if(matched) {
        // NEW: Extracts the params using the internal
        // function _extractParameters 
        params = Router._extractParameters(route, fragment);
        route = matched[1];
    }

    return {
        route : route,
        fragment : fragment,
        params : params
    };
}

请参阅前面的代码以获得进一步的评论和解释,它们看起来大致相同。

答案 2 :(得分:9)

要从被叫路由处理程序获取调用路由(或url),可以通过选中

来获取它
Backbone.history.location.href  ... the full url
Backbone.history.location.search  ... query string starting from ?

我来到这里寻找这个答案所以我想我应该留下我找到的东西。

答案 3 :(得分:6)

如果您使用路由器的根设置,您也可以将其包含在内以获取“真实”片段。

(Backbone.history.options.root || "") + "/" + Backbone.history.fragment

答案 4 :(得分:5)

这是 tad 更详细(或者,根据您的品味,更具可读性)版本的Simon's answer

current: function () {
  var fragment = Backbone.history.fragment,
      routes = _.pairs(this.routes),
      route,
      name,
      found;

  found = _.find(routes, function (namedRoute) {
    route = namedRoute[0];
    name = namedRoute[1];

    if (!_.isRegExp(route)) {
      route = this._routeToRegExp(route);
    }

    return route.test(fragment);
  }, this);

  if (found) {
    return {
      name: name,
      params: this._extractParameters(route, fragment),
      fragment: fragment
    };
  }
}

答案 5 :(得分:4)

如果您查看Router的来源,您会看到当路由器触发事件​​表明某些内容发生了变化时,它会将名称作为“route:name”传递给它。

http://documentcloud.github.com/backbone/docs/backbone.html#section-84

您始终可以在路由器上挂钩“路由”事件并将其存储以获取当前路由。

答案 6 :(得分:0)

router = new Backbone.Router.extend({
  routes: { "stuff/:id" : "stuff" },
  stuff: function(id) {}
});

router.on('route', function(route) {
  this.current = route;
});

现在,如果您导航到/stuff/1,则router.current将为“东西”