修改查询字符串而不重新加载页

我正在创建一个照片库,并希望能够更改查询字符串和标题时的照片浏览。

我所寻找的行为通常在一些连续/无限页面的实现中可以看到,当您向下滚动查询字符串时,页面编号(http://x.com?page=4)会不断增加,等等。这在理论上应该很简单,但是我想要一些在主流浏览器上是安全的东西。

我找到了 这个伟大的职位,并试图遵循 window.history.pushstate的例子,但这似乎并不适合我。我不确定它是否理想,因为我并不真正关心修改浏览器历史记录。

我只是想能够提供书签的能力,目前浏览的照片,而不是重新加载页面的每一次照片被改变。

下面是修改查询字符串的无限页的示例: http://tumbledry.org/

更新 发现了这个方法:

window.location.href = window.location.href + '#abc';
170165 次浏览

那么历史 API 正是您要寻找的。如果您也希望支持遗留浏览器,那么可以寻找一个在浏览器没有提供历史 API 的情况下依赖于操作 URL 的 hash 标记的库。

我使用以下 JavaScript 库取得了巨大的成功:

Https://github.com/balupton/jquery-history

它支持 HTML5历史 API 以及老式浏览器的回退方法(使用 #)。

这个库基本上是围绕“ history. pushState”的填充。

如果您正在寻找散列修改,那么您的解决方案可以正常工作。但是,如果您希望更改查询,则可以使用 pushState,如前所述。这里有一个示例可以帮助您正确地实现它。我测试过,效果很好:

if (history.pushState) {
var newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?myNewUrlQuery=1';
window.history.pushState({path:newurl},'',newurl);
}

它不重新加载页面,但只允许您更改 URL 查询。您将无法更改协议或主机值。当然,它需要能够处理 HTML5历史 API 的现代浏览器。

了解更多信息:

Http://diveintohtml5.info/history.html

Https://developer.mozilla.org/en-us/docs/web/guide/api/dom/manipulating_the_browser_history

基于 Fabio 的回答,我创建了两个函数,这两个函数可能对任何碰到这个问题的人都有用。使用这两个函数,您可以使用键和值作为参数调用 insertParam()。它将添加 URL 参数,或者,如果已经存在具有相同键的查询参数,它将把该参数更改为新值:

//function to remove query params from a URL
function removeURLParameter(url, parameter) {
//better to use l.search if you have a location/link object
var urlparts= url.split('?');
if (urlparts.length>=2) {


var prefix= encodeURIComponent(parameter)+'=';
var pars= urlparts[1].split(/[&;]/g);


//reverse iteration as may be destructive
for (var i= pars.length; i-- > 0;) {
//idiom for string.startsWith
if (pars[i].lastIndexOf(prefix, 0) !== -1) {
pars.splice(i, 1);
}
}


url= urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : "");
return url;
} else {
return url;
}
}


//function to add/update query params
function insertParam(key, value) {
if (history.pushState) {
// var newurl = window.location.protocol + "//" + window.location.host + search.pathname + '?myNewUrlQuery=1';
var currentUrlWithOutHash = window.location.origin + window.location.pathname + window.location.search;
var hash = window.location.hash
//remove any param for the same key
var currentUrlWithOutHash = removeURLParameter(currentUrlWithOutHash, key);


//figure out if we need to add the param with a ? or a &
var queryStart;
if(currentUrlWithOutHash.indexOf('?') !== -1){
queryStart = '&';
} else {
queryStart = '?';
}


var newurl = currentUrlWithOutHash + queryStart + key + '=' + value + hash
window.history.pushState({path:newurl},'',newurl);
}
}

我想改进法比奥的答案,并创建一个功能,添加自定义键的 URL 字符串,而不重新加载页面。

 function insertUrlParam(key, value) {
if (history.pushState) {
let searchParams = new URLSearchParams(window.location.search);
searchParams.set(key, value);
let newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?' + searchParams.toString();
window.history.pushState({path: newurl}, '', newurl);
}
}


// to remove the specific key
export function removeUrlParameter(paramKey) {
const url = window.location.href
console.log("url", url)
var r = new URL(url)
r.searchParams.delete(paramKey)
const newUrl = r.href
console.log("r.href", newUrl)
window.history.pushState({ path: newUrl }, '', newUrl)
}

因为每个回答这个问题的人似乎都忘记了散列,我想添加我用来保持 所有 URL 参数的代码:

const urlParams = new URLSearchParams(window.location.search);


/// Change some part of the URL params


if (history.pushState) {
const newurl =
window.location.protocol +
"//" +
window.location.host +
window.location.pathname +
"?" +
urlParams.toString() +
window.location.hash;
window.history.replaceState({ path: newurl }, "", newurl);
} else {
window.location.search = urlParams.toString();
}

我想给法比奥和阿兰姆的答案加点料。我想有时候我可能会喜欢保存在 url 中的散列。但通常不会,所以我将该参数设置为默认值 false

replaceState仍然没有在 Chrome 上设置页面标题。所以我添加了几行来更改标题(如果提供了一行的话)。

function insertUrlParam(key, value, title = '', preserve_hash = false) {
if (history.pushState) {
let searchParams = new URLSearchParams(window.location.search);
searchParams.set(key, value);
let newurl = window.location.protocol + "//" + window.location.host + window.location.pathname
+ '?' + searchParams.toString();
if(preserve_hash) newurl = newurl + window.location.hash;
let oldTitle = document.title;
if(title !== '') {
window.history.replaceState({path: newurl}, title, newurl);
if(document.title !== title) { // fallback if above doesn't work
document.title = title;
}
} else { // in case browsers ever clear titles set with empty string
window.history.replaceState({path: newurl}, oldTitle, newurl);
}
}
}

如果我们只是想更新查询参数而不接触 URL 的其他部分,那么就没有必要再次构建 URL。我用的是这个:

const addQueryParam = (key, value) => {
const url = new URL(window.location.href);
url.searchParams.set(key, value);
window.history.pushState({}, '', url.toString());
};


const getQueryParam = (key) => {
const url = new URL(window.location.href);
return url.searchParams.get(key) || '';
};

古老的问题,现代的答案,以帮助未来的开发人员; 使用 网址接口:

const url = new URL(window.location);
url.searchParams.set('key', value);
window.history.pushState(null, '', url.toString());

这确保您真的只更改所需的查询参数。