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

Posted

技术标签:

【中文标题】修改查询字符串而不重新加载页面【英文标题】:Modifying a query string without reloading the page 【发布时间】:2012-06-13 18:23:26 【问题描述】:

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

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

我找到了this great post,并试图以window.history.pushstate 为例,但这似乎对我不起作用。而且我不确定它是否理想,因为我并不真正关心修改浏览器历史记录。

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

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

UPDATE找到了这个方法:

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

【问题讨论】:

你能发布一个链接到一些动态更新其查询字符串的示例网站吗?我不认为它可以做到,但你可以改变哈希值,这可能足以得到你想要的。 how to manipulate the URL with javascript/jquery?的可能重复 How does GitHub change the URL but not the reload?的可能重复 Why the new web Dropbox can change the URL without page refresh? 的可能重复以及它被标记为重复的三个问题 @昆汀。你只能有一个更接近的投票...:) 【参考方案1】:

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

【讨论】:

我相信您可以将window.location.protocol + '//' + window.location.host 缩短为:window.location.origin 另外,关于附加信息,相对路径也适用于history.pushState()。也不需要实际的 state 参数。这两个都意味着你可以做一些简单的事情,比如history.pushState(null, '', '/foo?bar=true'),如果你的新网址在同一个主机/端口上。 请注意,如果您不希望新状态出现在浏览器历史记录中,您可以使用 history.replaceState() 和相同的参数。 使用 history.replaceState() 否则你需要在浏览器中点击两次 BACK 按钮 在现代浏览器中你可以这样做:if (window.history.pushState) const newURL = new URL(window.location.href); newURL.search = '?myNewUrlQuery=1'; window.history.pushState( path: newURL.href , '', newURL.href); 【参考方案2】:

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

【讨论】:

这是问题的确切答案。谢谢 太棒了,谢谢!【参考方案3】:

在 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() 将其写入历史 new URLSearchParams() 不受任何版本的 IE 支持 谢谢@jmona789 这对我来说非常有效,正是我想要的【参考方案4】:

我成功使用了以下 JavaScript 库:

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

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

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

【讨论】:

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

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

【讨论】:

【参考方案6】:

如果我们只是想更新查询参数而不触及 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) || '';
;

【讨论】:

【参考方案7】:

旧问题,现代答案可帮助未来的开发者;使用URL 接口:

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

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

【讨论】:

【参考方案8】:

那么历史 API 正是您正在寻找的。如果您也希望支持旧版浏览器,那么在浏览器不提供历史 API 的情况下,寻找一个库来处理 URL 的哈希标记。

【讨论】:

【参考方案9】:

我想我会在 Fabio 和 Aram 的回答中添加一些内容。我想我有时可能想在 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 查询字符串

在页面重新加载时删除查询字符串

是否可以修改网页的源并重新加载该页面而不是从服务器而是从编辑的源?

我们如何在不重新加载页面的情况下使用 javascript/jQuery 更新 URL 或查询字符串?

如果 localStorage 值存在而不重新加载页面,则 Javascript 添加类

更新图像而不闪烁 ASP.NET C#