ChatGPT解决这个技术问题 Extra ChatGPT

Backbone.js:获取当前路由

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

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

R
Robert

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

Backbone.history.getFragment();

Backbone.js documentation

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

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

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() )
C
Community

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

有关进一步的评论和解释,请参阅前面的代码,它们看起来几乎相同。


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

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

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

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


n
n0nick

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

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

C
Community

这是一个稍微更详细(或者,根据您的口味,更易读)的 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
    };
  }
}

B
Brian Genisio

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

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

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


好的,我想这是“自己建造”之类的东西。
是的,但如果 trigger 不是 true(推荐和默认),您将不会收到 route 事件。
链接不再有效。
D
Dave Aaron Smith
router = new Backbone.Router.extend({
  routes: { "stuff/:id" : "stuff" },
  stuff: function(id) {}
});

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

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


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅