【问题标题】:When I push a new URL to Backbone.history, the query params stays?当我将新 URL 推送到 Backbone.history 时,查询参数会保留吗?
【发布时间】:2013-03-01 19:48:32
【问题描述】:

假设我正在使用 Backbone pushstate,并导航到带有查询参数的页面:

domain.com/user/111?hello=123

当我执行这个时:

Backbone.history.navigate('/settings', true);

我的设置页面加载完美,但 ?hello=123 保留在 URL 中...

domain.com/settings?hello=123

并且该查询参数在我浏览网站的任何地方都保留在 URL 中...

【问题讨论】:

  • 编辑:我正在使用github.com/jhudson8/backbone-query-parameters 插件。
  • 你能把这个问题说得更清楚一点吗?您想在导航到另一个页面时清空location.search
  • 似乎 2 天前在 github 上也发布了一个问题,而作者似乎没有使用该功能。
  • 你启用pushState了吗? Backbone.history.start( { pushState : true } );

标签: javascript html url backbone.js pushstate


【解决方案1】:

骨干路由和查询参数是不愉快的结合。问题在this GitHub issue 中有详细记录。

核心问题是Backbone.Router 设计用于处理 URL 哈希片段以及 pushState API。当使用哈希 URL 时,查询字符串在哈希之前,并且在路由中永远不会匹配。对于 pushState,查询字符串是 URL 片段的一部分,并且需要不同的路由表达式。

假设您有一个路由search,并且该路由可以选择采用参数qsorttype。作为一个查询字符串,看起来像:

search?q=kittens&sort=asc&type=images

问题是,对于旧浏览器的用户,Backbone 将恢复为基于hashchange 的路由,并且路由将变为:

?q=kittens&sort=asc&type=images#search

您使用的插件试图解决这个问题,但没有解决核心问题。

如果可能,您应该考虑不使用查询字符串,并在路由表达式中使用可选片段传递任何状态信息。前面的示例路由将变为:

//pushState
search/q/kittens/sort/asc/type/images

//hash fragment
#search/q/kittens/sort/asc/type/images

使用(optional) 路由部分和:captures (docs),您可以使用以下表达式表示此 URL:

var Router = Backbone.Router.extend({
  routes: {
    "search(/q/:query)(/sort/:sort)(/type/:type)": "search"
  },

  search: function(query, sort, type) {
    console.log(query, sort, type); //-> "kittens", "asc", "images" 
  }
});

只要路由片段按照指定的顺序,这将匹配带有none、any和all参数的url,例如:

search                       //->  undefined,  undefined, undefined
search/q/kittens/type/images //->  "kittens",  undefined, "images"
search/sort/asc/type/images  //->  undefined,  "asc",     "images"

这样您就不必担心第三方查询字符串库或浏览器兼容性问题。如果你问我,后一种类型的 URL 看起来也更简洁。

【讨论】:

  • 认为以斜杠的方式放置太多参数违背了 RESTful URL 的原则。加上@TIMEX 的问题是由插件引起的。我知道骨干正在推动斜线时尚,但我确实认为获取样式参数最适合某些特定功能,例如搜索。
  • 不错的解决方案。这只是客户端,所以 RESTful URL 的想法在这里并不适用。任何有效的网址都可以。
  • @jasop 我不同意。 RESTful URL 不仅仅是实现细节的问题。它们也是面向用户的,理想情况下应该遵守 RESTful 标准,以确保整个 Web 的一致性。当然,这是对 RESTful 约定的相当良性的破坏。我并不是说没有有效的理由来打破约定,只是我认为它是客户端 URL 的事实不应该成为理由的一部分。
  • @acjohnson55 是的,为了保持一致性,最好让客户端 URL 也看起来是 RESTful。我试图说明的一点是,很多人可能会对浏览器和服务 URL 感到困惑。使您的服务 RESTful 是最重要的。出于多种原因,我不会在这里讨论。然而,浏览器中的 URL 与所有这些都是分开的。看起来像 RESTful URL 会很好,但浏览器 URL 与 REST 无关。人们了解两者之间的区别很重要。
【解决方案2】:

您不必再使用backbone-query-parameters 插件来处理这个问题,只需确保您拥有最新版本的Backbone,然后覆盖History.prototype 中的loadUrl 方法即可。

// Regex to match search query strings
var searchStripper = /\?.*$/g;

// Attempt to load the current URL fragment. If a route succeeds with a
// match, returns `true`. If no defined routes matches the fragment,
// returns `false`.
loadUrl: function(fragmentOverride) {
  var fragment = this.fragment = this.getFragment(fragmentOverride);
  fragment = fragment.replace(searchStripper, ''); // remove the search query parameter
  var matched = _.any(this.handlers, function(handler) {
    if (handler.route.test(fragment)) {
      handler.callback(fragment);
      return true;
    }
  });
  return matched;
},

【讨论】:

  • 这不是也从初始 URL user/111 中剥离 URL 参数,@TIMEX 大概希望保持查询字符串完整?在使用基于哈希的 URL 时,它也不能解决问题,因为查询字符串根本不是片段的一部分。
【解决方案3】:

不确定是否为时已晚。我遇到了同样的问题,我可以自信地说:这是一个由主干查询参数引起的错误。

我实际上是受到您的帖子的启发。在我当前项目的早期,我引入了主干查询参数,它运行良好。但后来,主干进行了一些更改,因此主干查询参数无法再获取参数。直到最近才发现作者升级了backbone-query-parameters。我又把它拉进去了,它起作用了。

那么,你知道的。我遇到了同样的问题,感到非常沮丧。我从来没有怀疑过骨干查询参数,直到我看到你的帖子。

我删除了插件并配备了我自己的代码,现在我的历史就像一个魅力。

有许多方法可以获取 get 参数。我的只是其中之一,但它为我完成了这项工作。仅供参考,我在这里发布。

  getParams: ->
    rtn = {}

    if window.location.search.length > 0
      queryStringRegex =  /^\?(.*)/
      match = queryStringRegex.exec window.location.search
      param_string = match[1]

      if param_string.length > 0
        params_array = param_string.split("&")

        for value in params_array
          temp = value.split("=")
          rtn[temp[0]] = decodeURI(temp[1])

    rtn

以防万一,我的路线会是这样的

"path(?*queryString)" : "pathAction"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 1970-01-01
    相关资源
    最近更新 更多