2013-03-01 58 views
13

比方說,我使用的骨幹pushState的和我瀏覽到一個頁面,查詢參數:當我推送一個新的URL到Backbone.history時,查詢參數保持?

domain.com/user/111?hello=123 

當我執行此:

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

我的設置頁面加載完美,但你好=? 123只停留在網址...

domain.com/settings?hello=123 

這查詢參數停留在URL我到處瀏覽網站...

+0

編輯:我使用的是https://github.com/jhudson8/backbone-query-parameters插件。 – TIMEX 2013-03-02 23:42:30

+0

你能否讓問題更清楚一點?你想在每次導航到另一個頁面時清空'location.search'? – 2013-03-03 22:56:05

+0

在[github](https://github.com/jhudson8/backbone-query-parameters/issues/29)上似乎也發佈了一個關於2天前發佈的問題,作者似乎沒有在該功能上工作。 – Starx 2013-03-03 23:05:48

回答

19

骨幹路由和查詢參數是一個不幸的婚姻。問題在this GitHub issue中有詳細記錄。

核心問題是Backbone.Router被設計爲與URL散列片段以及pushState API一起工作。使用散列URL時,查詢字符串位於散列之前,並且在路由中從不匹配。使用pushState,查詢字符串是URL片段的一部分,並且需要不同的路由表達式。

假設你有一個路線search,並且路線將可選帶參數qsorttype。作爲查詢字符串看起來像:

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

的問題是,對於老的瀏覽器用戶,骨幹將恢復到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)線路零件和:capturesdocs),你可以代表此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" 
    } 
}); 

只要路線片段中按照指定的順序,這將匹配沒有,任何和所有參數的URL,例如:

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

該W您不必擔心第三方查詢字符串庫或瀏覽器兼容性問題。如果你問我,後一種類型的URL看起來更乾淨。

+1

認爲以斜槓方式放置太多參數違背了RESTful URL的原則。 Plus @ TIMEX的問題是由插件引起的。我知道中堅力量正在推動斜線時尚,但我認爲讓風格參數適合一些特定的功能,如搜索最佳。 – yujingz 2013-04-04 07:12:12

+0

很好的解決方案。這只是客戶端,所以RESTful URL的概念在這裏不適用。任何工作的URL都可以。 – jasop 2013-07-08 14:59:28

+0

@jasop我不同意。 REST風格的URL不僅僅是實現細節的問題。它們也面向用戶,爲了網絡的一致性,應該遵守RESTful標準。當然,這是對RESTful慣例的一個相當溫和的打破。我並不是說沒有合理的理由來打破慣例,只是我認爲它是客戶端URL的事實不應該成爲理由的一部分。 – acjay 2014-01-28 15:17:54

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; 
}, 
+0

這是否也會剝離初始URL user/111的URL參數,其中@TIMEX大概是想保持查詢字符串不變?當使用基於散列的URL時,它也不能解決問題,其中查詢字符串根本不是片段的一部分。 – jevakallio 2013-03-04 14:04:55

0

不確定是否爲時已晚。我遇到了同樣的問題,我可以自信地說:這是一個由主幹查詢參數引起的錯誤。

其實我的靈感來自你的文章。在我當前項目的早期階段,我介紹了骨幹查詢參數,它運行良好。但後來,主幹進行了一些更改,以便骨幹查詢參數不能再更改參數。直到最近,我發現作者升級了骨幹查詢參數。我再次拉它,它工作。

然後,你知道。我喜歡同樣的問題,並感到非常沮喪。我從來沒有懷疑骨幹查詢參數,直到我看到您的帖子。

我刪除了插件,並配備了自己的代碼,現在我的歷史就像一個魅力。

有很多方法來獲取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" 
相關問題