【问题标题】:Backbone.js: get current routeBackbone.js:获取当前路由
【发布时间】:2011-11-25 17:02:28
【问题描述】:

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

【问题讨论】:

  • “名称”是指该路由绑定的函数,还是当前 URL 或 URL 的哈希部分是什么?
  • 哦,是的,我应该更具体一些。我想知道函数的名称。 (我知道如何通过 location.hash 或 Backbone.history.fragment 获取 URL 的哈希部分。)

标签: backbone.js


【解决方案1】:
router = new Backbone.Router.extend({
  routes: { "stuff/:id" : "stuff" },
  stuff: function(id) {}
});

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

现在如果你导航到/stuff/1,router.current 将是“东西”

【讨论】:

    【解决方案2】:

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

    Backbone.history.getFragment();
    

    来自Backbone.js documentation

    " [...] History 作为一个全局路由器(每帧)来处理 hashchange 事件或 pushState,匹配适当的路由,并触发回调。您永远不必自己创建其中之一 - 如果您使用带有路线。 [...]”

    如果您需要绑定到该片段的函数的名称,您可以在路由器的范围内进行类似的操作:

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

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

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

    【讨论】:

    • 谢谢,太好了。我似乎从未在文档中提及 Backbone.history.fragment。这是新增内容,还是没有记录?
    • 我认为这是无证的。实际上,我不记得我第一次看到它是在哪里,某个博客或者可能是主干源代码。
    • 仅供参考,这不适用于 'foo/:id' 或 'bar*params' 等路由
    • 最好使用Backbone.history.getFragment(),因为Backbone.history.fragment是私有的隐藏属性。
    • 我已按照@Vad 的建议更正了答案。我不再使用 Backbone,但他的评论对我来说是正确的。 (之前的答案是:Backbone.history.fragment 而不是 Backbone.history.getFragment())
    【解决方案3】:

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

    因为我需要这个功能,所以我用 current 函数扩展了 Backbone.Router,它重用了 History 和 Router 对象用来将当前片段与定义的路由匹配以触发适当的回调的一些代码。 对于我的用例,它采用可选参数route,如果设置为任何真实值,将返回为路由定义的相应函数名称。否则,它将从Backbone.History.fragment 返回当前的哈希片段。

    您可以将代码添加到您现有的扩展中,并在其中初始化和设置主干路由器。

    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 对象即可轻松创建此功能。我这样做是因为它是我设置的最方便的方式。

    我尚未对此进行全面测试,所以如果有任何问题请告诉我。


    2013 年 4 月 25 日更新

    我对函数做了一些更改,因此我没有返回哈希或路由回调名称,而是返回一个带有片段、参数和路由的对象,这样您就可以从当前路由访问所有数据,就像您从路线事件。

    你可以看到下面的变化:

    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
        };
    }
    

    更多 cmets 和解释请参见前面的代码,它们看起来基本相同。

    【讨论】:

    • 本来打算自己写的,但先用谷歌搜索了解决方案。很高兴我做到了。你的正是我想要的,谢谢!
    • 这是一个slightly more verbose version,我相信乍一看更容易理解。
    • 哇,谢谢!您刚刚在我们的代码库中得到了确认。 ;P 我们为 Marionette 稍微调整了它。顺便说一句,作为一种快捷方式,您可以将_.find 函数的第三个参数(设置上下文)设置为this,从而消除对Router 变量的需要(@DanAbramov 已经这样做了)。跨度>
    • @Mark 这些都是好消息。但是我怎样才能在木偶中使用这个功能呢?文档中没有任何内容。
    • @darksoulsong 如果您使用的是Marionette.AppRouter,请使用上述功能扩展您的路由器,但用Router.appRoutes 替换Router.routes
    【解决方案4】:

    这是Simon's answertad 更详细(或者,根据您的口味,更易读)的版本:

    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】:

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

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

      【讨论】:

        【解决方案6】:

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

        Backbone.history.location.href ...完整的网址 Backbone.history.location.search ... 从 ? 开始的查询字符串

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

        【讨论】:

          【解决方案7】:

          如果您查看Router 的源代码,您会发现当路由器触发表明某事发生变化的事件时,它会将名称作为“route:name”传递。

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

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

          【讨论】:

          • 好吧,我猜这是“自己建造”之类的东西。
          • 是的,但如果trigger 不是 true(推荐和默认),您将不会收到route 事件。
          • 链接不再有效。
          猜你喜欢
          • 1970-01-01
          • 2021-07-22
          • 2021-06-21
          • 2015-11-16
          • 2021-06-30
          • 2016-04-01
          • 1970-01-01
          • 2016-12-29
          • 2019-08-17
          相关资源
          最近更新 更多