修改查询字符串而无需重新加载页面


114

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

我正在寻找的行为经常出现在连续/无限页面的某些实现中,其中当您向下滚动查询字符串时会不断增加页面编号(http://x.com?page=4)等。这应该是从理论上讲很简单,但我希望在主要的浏览器中都能安全使用。

我找到了这篇不错的文章,并尝试使用跟随该示例window.history.pushstate,但这似乎对我没有用。而且我不确定它是否理想,因为我不太在乎修改浏览器的历史记录。

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

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

UPDATE找到此方法:

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

它似乎适合我,但我使用的是新的Chrome。这可能会导致旧版浏览器出现某些问题?


您可以发布指向一些示例站点的链接,以动态更新其查询字符串吗?我不认为这是可以完成的,但是您可以更改哈希值,这可能足以获取所需的值。
Pointy 2012年



为什么新的Web Dropbox可以更改URL而无需刷新页面的可能重复项及其三个问题被标记为重复
Quentin 2012年

@昆汀 您只能进行更近的投票...:)
gdoron支持Monica 2012年

Answers:


185

如果您正在寻找哈希修改,您的解决方案就可以了。但是,如果您想更改查询,则可以使用您所说的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/zh-CN/docs/Web/Guide/API/DOM/Manipulating_the_browser_history


6
我相信您可以缩短window.location.protocol + '//' + window.location.host为: window.location.origin
加勒特

4
另外,要获取更多信息,相对路径也可以使用history.pushState()。也不state要求任何实际参数。两者都意味着您可以做一些简单的事情,例如history.pushState(null, '', '/foo?bar=true')如果您的新URL位于同一主机/端口上。
Blaskovicz

23
请注意,如果您不希望新状态出现在浏览器历史记录中,则可以使用history.replaceState()相同的参数。
Blackus

6
请使用history.replaceState(),否则您需要在浏览器中单击两次“上一步”按钮
Zhenya

4
在现代浏览器中,您可以做到:if (window.history.pushState) { const newURL = new URL(window.location.href); newURL.search = '?myNewUrlQuery=1'; window.history.pushState({ path: newURL.href }, '', newURL.href); }
Allan Baptista,

8

在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()设置删除本机方法相比,您的功能如何更好?无论哪种情况,我们都必须与history.pushState()
AlexNikonov

1
new URLSearchParams()的任何版本的IE都不支持
jmona789

谢谢@ jmona789,这对我来说非常有效,而这正是我在寻找的东西
mknopf

7

我成功使用了以下JavaScript库:

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

它支持HTML5历史记录API以及旧版浏览器的后备方法(使用#)。

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


太棒了!您是否在所有浏览器上对其进行了测试?
Sonic Soul 2012年

我的实现已在IE7 +,Firefox 3.6 +,Safari 5和Chrome 16+中进行了测试。它可能也可以与其他浏览器一起使用,但是在使用它部署的多个系统中我没有任何抱怨。
伊恩·纽森

大。所以现在..在写入window.location.href时,只需输入#而不是&即可。因为它不会重新加载页面。我敢肯定,一旦我在IE中测试它,它就会崩溃。那时,我将使用您建议的库。谢谢
Sonic Soul

#方法是一个很好的方法,因为它具有非常广泛的浏览器支持。当您需要将该信息包含在对服务器的请求中时,事情会变得复杂,因为URL的#部分不是由浏览器发送的。有很多方法可以解决,其中包括我引用的库。另外,使用HTML5历史记录API有助于使您的URL整体更短,并且需要较少的客户端工作来恢复状态。
伊恩·纽森

#方法对于社交媒体共享也有问题;创建预览或返回共享的链接时,Twitter,Facebook和其他可能无法与锚标记一起很好地使用。
mirth23 '18 / 10/24

5

我想改善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);
    }
}

0

那么历史API正是您要寻找的。如果您也希望支持旧版浏览器,那么如果浏览器不提供历史记录API,则寻找一个可以处理URL的hash标签的库。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.