当我将新URL推送到Backbone.history时,查询参数保持不变?

TIM*_*MEX 13 javascript url html5 backbone.js pushstate

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

domain.com/user/111?hello=123
Run Code Online (Sandbox Code Playgroud)

当我执行这个:

Backbone.history.navigate('/settings', true);
Run Code Online (Sandbox Code Playgroud)

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

domain.com/settings?hello=123
Run Code Online (Sandbox Code Playgroud)

并且该查询参数保留在我浏览网站的所有位置的URL中...

jev*_*lio 19

骨干路由和查询参数是一个不愉快的婚姻.GitHub问题中记录了很多问题.

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

假设你有一条路线search,那条路线可以选择参数q,sorttype.作为查询字符串,看起来像:

search?q=kittens&sort=asc&type=images
Run Code Online (Sandbox Code Playgroud)

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

?q=kittens&sort=asc&type=images#search
Run Code Online (Sandbox Code Playgroud)

您使用的插件尝试解决此问题,但不解决核心问题.

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

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

//hash fragment
#search/q/kittens/sort/asc/type/images
Run Code Online (Sandbox Code Playgroud)

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

只要路径片段按指定顺序排列,这将使url与none,any和all参数匹配,例如:

search                       //->  undefined,  undefined, undefined
search/q/kittens/type/images //->  "kittens",  undefined, "images"
search/sort/asc/type/images  //->  undefined,  "asc",     "images"
Run Code Online (Sandbox Code Playgroud)

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