Backbone.js:获取当前路由

Dre*_*ams 135 backbone.js

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

Rob*_*ert 209

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

Backbone.history.getFragment();
Run Code Online (Sandbox Code Playgroud)

Backbone.js文档:

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

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

alert( this.routes[Backbone.history.getFragment()] );
Run Code Online (Sandbox Code Playgroud)

或者从你的路由器外面这样:

alert( myRouter.routes[Backbone.history.getFragment()] );
Run Code Online (Sandbox Code Playgroud)

  • 仅供参考,这不适用于'foo /:id'或'bar*params'等路线 (24认同)
  • 更好地使用`Backbone.history.getFragment()`,因为`Backbone.history.fragment`是一个隐私属性. (2认同)

Sim*_*erg 56

罗伯特的答案很有意思,但遗憾的是,只有当哈希完全按照路线中的定义时,它才会起作用.例如,如果您有一条路线,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'
Run Code Online (Sandbox Code Playgroud)

我确信可以做一些改进,但这是一个让你入门的好方法.此外,在不扩展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
    };
}
Run Code Online (Sandbox Code Playgroud)

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

  • 哇,谢谢你!您刚收到我们的代码库中的确认.; P我们稍微调整了Marionette.顺便说一句,作为一个快捷方式,您可以将`_.find`函数的第三个参数(设置上下文)设置为`this`,从而无需使用`Router`变量(@DanAbramov已经这样做了). (4认同)
  • @darksoulsong如果您正在使用`Marionette.AppRouter`,请使用上面的函数扩展您的路由器,但将`Router.appRoutes`替换为`Router.routes`. (2认同)

yos*_*shi 10

要从被调用的路由处理程序获取调用路由(或url),可以通过检查来获取它

Backbone.history.location.href  ... the full url
Backbone.history.location.search  ... query string starting from ?

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


小智 6

如果您使用路由器的根设置,您还可以包含它以获取"真实"片段.

(Backbone.history.options.root || "") + "/" + Backbone.history.fragment
Run Code Online (Sandbox Code Playgroud)


Dan*_*mov 5

这里有一个稍微更详细的(或者,取决于你的口味,更易读)的版本西蒙的回答:

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
    };
  }
}
Run Code Online (Sandbox Code Playgroud)