在不重新加载页面的情况下修改查询字符串

IT技术 javascript jquery query-string dhtml
2021-03-03 16:42:55

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

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

我找到了这篇很棒的帖子,并试图按照示例进行操作window.history.pushstate,但这似乎对我不起作用。而且我不确定它是否理想,因为我并不真正关心修改浏览器历史记录。

我只是希望能够为当前查看的照片添加书签,而无需在每次更改照片时重新加载页面。

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

更新发现这个方法:

window.location.href = window.location.href + '#abc';

它似乎对我有用,但我使用的是新的 chrome.. 它可能会导致旧浏览器出现一些问题?

6个回答

如果您正在寻找哈希修改,则您的解决方案可以正常工作。但是,如果您想更改查询,则可以使用 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 History API 的现代浏览器。

想要查询更多的信息:

http://diveintohtml5.info/history.html

https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history

请注意,如果您不希望新状态出现在浏览器历史记录中,您可以使用history.replaceState()相同的参数。
2021-04-30 16:42:55
在现代浏览器中,您可以这样做: if (window.history.pushState) { const newURL = new URL(window.location.href); newURL.search = '?myNewUrlQuery=1'; window.history.pushState({ path: newURL.href }, '', newURL.href); }
2021-05-01 16:42:55
我相信你可以缩短window.location.protocol + '//' + window.location.host为: window.location.origin.
2021-05-03 16:42:55
此外,对于额外的信息,相对路径也适用于history.pushState(). 也不state需要实际论证。这两者都意味着你可以做一些简单的事情,比如history.pushState(null, '', '/foo?bar=true')如果你的新 url 在同一个主机/端口上。
2021-05-18 16:42:55
使用 history.replaceState() 否则你需要在浏览器中点击两次返回按钮
2021-05-20 16:42:55

我想改进 Fabio 的答案并创建一个函数,该函数在不重新加载页面的情况下向 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);
    }
}
这是问题的确切答案。谢谢
2021-04-27 16:42:55
太棒了,谢谢!
2021-05-09 16:42:55

在 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);
    }
}
你的函数如何比new URLSearchParams()它的本地方法setdelete更好在任何一种情况下,我们都必须把它放到历史中history.pushState()
2021-05-08 16:42:55
new URLSearchParams() 任何版本的 IE 都不支持
2021-05-15 16:42:55
谢谢@jmona789 这对我来说非常有效,这正是我正在寻找的
2021-05-18 16:42:55

我已经成功地使用了以下 JavaScript 库:

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

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

这个库本质上是一个围绕“history.pushState”的 polyfill。

# 方法是一个很好的方法,因为它具有非常广泛的浏览器支持。当您需要在对服务器的请求中包含该信息时,事情会变得复杂,因为 URL 的 # 部分不是由浏览器发送的。有很多方法可以解决这个问题,其中包括我引用的库。此外,使用 HTML5 历史 API 有助于使您的 URL 整体更短,并且需要更少的客户端工作来恢复状态。
2021-04-21 16:42:55
# 方法对于社交媒体共享也有问题;在创建预览或返回共享的链接时,Twitter、Facebook 和可能的其他人不能很好地使用锚标记。
2021-04-21 16:42:55
惊人的!你用所有浏览器测试过吗??
2021-04-30 16:42:55
伟大的。所以现在.. 在写入 window.location.href 时只需用 # 而不是 & 对我有用。因为它不会重新加载页面。我敢肯定,一旦我在 IE 中测试它,它就会坏掉。谢谢
2021-05-07 16:42:55
我的实现在 IE7+、Firefox 3.6+、Safari 5 和 Chrome 16+ 中进行了测试。它可能也适用于其他浏览器,但我在使用它部署的几个系统中没有任何抱怨。
2021-05-13 16:42:55

由于每个回答这个问题的人似乎都忘记了哈希,我想添加我用来保留所有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();
}