使用JavaScript更改URL参数并指定默认值

243

我有这个 URL:

site.fwx?position=1&archiveid=5000&columns=5&rows=20&sorting=ModifiedTimeAsc

我需要做的是能够更改“rows”URL参数的值为我指定的值,比如说10。如果“rows”不存在,我需要将其添加到URL末尾,并添加我已经指定的值(10)。


13
我很难相信现在已经是2013年了,还没有更好的方法来做到这一点,比如将其构建到核心浏览器库中。 - Tyler Collier
8
@TylerCollier 中2015年至今仍然没有任何进展 :( - Tejas Manohar
4
看起来我们已经接近目标了... https://developer.mozilla.org/zh-CN/docs/Web/API/URLSearchParams/URLSearchParams#浏览器兼容性 - chris
13
@TylerCollier 现在是2021年,我们终于搞定了 :) const myUrl = new URL("http://www.example.com?columns=5&rows=20"); myUrl.searchParams.set('rows', 10); myUrl.href 将包含更新后的URL - sprutex
2
根据@sprutex的评论,您可以将http://www.example.com?columns=5&rows=20替换为window.location.href以使代码更具动态性。 - Waleed Khaled
显示剩余5条评论
32个回答

134

我已经扩展了Sujoy的代码以创建一个函数。

/**
 * https://dev59.com/enNA5IYBdhLWcg3wGJ0V#10997390
 */
function updateURLParameter(url, param, paramVal){
    var newAdditionalURL = "";
    var tempArray = url.split("?");
    var baseURL = tempArray[0];
    var additionalURL = tempArray[1];
    var temp = "";
    if (additionalURL) {
        tempArray = additionalURL.split("&");
        for (var i=0; i<tempArray.length; i++){
            if(tempArray[i].split('=')[0] != param){
                newAdditionalURL += temp + tempArray[i];
                temp = "&";
            }
        }
    }

    var rows_txt = temp + "" + param + "=" + paramVal;
    return baseURL + "?" + newAdditionalURL + rows_txt;
}

函数调用:

var newURL = updateURLParameter(window.location.href, 'locId', 'newLoc');
newURL = updateURLParameter(newURL, 'resId', 'newResId');

window.history.replaceState('', '', updateURLParameter(window.location.href, "param", "value"));

更新的版本还可以处理URL上的锚点。

function updateURLParameter(url, param, paramVal)
{
    var TheAnchor = null;
    var newAdditionalURL = "";
    var tempArray = url.split("?");
    var baseURL = tempArray[0];
    var additionalURL = tempArray[1];
    var temp = "";

    if (additionalURL) 
    {
        var tmpAnchor = additionalURL.split("#");
        var TheParams = tmpAnchor[0];
            TheAnchor = tmpAnchor[1];
        if(TheAnchor)
            additionalURL = TheParams;

        tempArray = additionalURL.split("&");

        for (var i=0; i<tempArray.length; i++)
        {
            if(tempArray[i].split('=')[0] != param)
            {
                newAdditionalURL += temp + tempArray[i];
                temp = "&";
            }
        }        
    }
    else
    {
        var tmpAnchor = baseURL.split("#");
        var TheParams = tmpAnchor[0];
            TheAnchor  = tmpAnchor[1];

        if(TheParams)
            baseURL = TheParams;
    }

    if(TheAnchor)
        paramVal += "#" + TheAnchor;

    var rows_txt = temp + "" + param + "=" + paramVal;
    return baseURL + "?" + newAdditionalURL + rows_txt;
}

我似乎无法让它工作。这是我的代码:http://jsfiddle.net/Draven/tTPYL/1/URL看起来像http://www.domain.com/index.php?action=my_action&view-all=Yes,我需要更改“view-all”的值。我的SO问题已关闭:http://stackoverflow.com/questions/13025880/js-append-variable-to-url-without-repeating - Draven
1
使用"var i=0"代替"i=0",以防止创建/修改i作为全局变量。 - Jonathan Aquino
2
这个函数还有几个问题:(1) paramVal没有进行URI编码。(2) 如果paramVal为空,则会得到foo=null。应该是foo=(或者更好的方法是完全删除foo)。 - Jonathan Aquino
@JonathanAquino 我也希望在 paramVal === null 时删除参数。 为此,我已将最后2行替换为以下内容:if ( paramVal !== null ) newAdditionalURL += temp + '' + param + '=' + paramVal; return baseURL + '?' + newAdditionalURL; - caiosm1005
很棒的答案!顺便提一下,不需要将 "" 连接到字符串上:var rows_txt = temp + "" + param + "=" + paramVal; - HoldOffHunger
显示剩余5条评论

95
我认为你想要使用查询插件

例如:

window.location.search = jQuery.query.set("rows", 10);

无论行的当前状态如何,这都将起作用。


2
将URL中的奇怪字符替换成有效的UTF-8字符,或者换句话说,“更改查询字符串只使用有效的UTF-8字符”。 :) F8单独并不是一个有效的UTF-8字符。 - Matthew Flaschen
有没有一种方法可以从这个插件中检索基本URL?例如,如果我的URL是'http://www.youtube.com/watch?v=PZootaxRh3M',则获取'http://www.youtube.com/watch'。 - Matt Norris
3
@Wraith,你不需要插件来实现那个。只需使用window.location.pathname即可。 - Matthew Flaschen
我现在不是在处理页面的URL吗?我想要获取任何旧的URL并替换查询字符串。 - Brad Urani
2
@MattNorris 你不需要插件,但正确的答案是: window.location.host + window.location.pathname 在你的情况下,它将是 "www.youtube.com/watch" - nktssh
显示剩余2条评论

82

用纯js快速解决方案,无需插件:

function replaceQueryParam(param, newval, search) {
    var regex = new RegExp("([?;&])" + param + "[^&;]*[;&]?");
    var query = search.replace(regex, "$1").replace(/&$/, '');

    return (query.length > 2 ? query + "&" : "?") + (newval ? param + "=" + newval : '');
}

这样调用它:
 window.location = '/mypage' + replaceQueryParam('rows', 55, window.location.search)

或者,如果您希望保留在同一页上并替换多个参数:
 var str = window.location.search
 str = replaceQueryParam('rows', 55, str)
 str = replaceQueryParam('cols', 'no', str)
 window.location = window.location.pathname + str

编辑,感谢Luke:要完全删除参数,请将值传递为falsenullreplaceQueryParam('rows', false, params)。由于0也是假的,请指定'0'


2
同样,要从输出中删除一个已使用的参数,请执行以下操作:str = replaceQueryParam('oldparam', false, str) - 基本上将一个假值类型放入其中。 - Luke Wenke
1
存在问题,无故复制我的参数,请查看此类似解决方案https://dev59.com/p2w05IYBdhLWcg3wiyfg#20420424 - azerafati
@Bludream,这段代码已经在生产环境中运行多年了。我还没有看到它重复参数。你能否发布一个重现或更有建设性的信息? - bronson
1
@dVyper 正确,一个假值会完全删除该参数。请使用文本“0”代替整数0。 - bronson
1
这虽然有点老,但对我来说完美无缺。它简短、干净、易于修改,并最终完成了我所需的工作。谢谢。 - BlueSun3k1
显示剩余3条评论

82

四年后,经过了很多学习,我自己回答了这个问题。特别是要注意不要把jQuery用于所有事情上。我创建了一个简单的模块,可以解析/字符串化查询字符串。这使得修改查询字符串变得容易。

你可以按照以下方式使用query-string

// parse the query string into an object
var q = queryString.parse(location.search);
// set the `row` property
q.rows = 10;
// convert the object to a query string
// and overwrite the existing query string
location.search = queryString.stringify(q);

1
哇,这是一个非常简单而明智的解决方案。谢谢! - jetlej
这个东西跑得飞快!谢谢Sindre(你只需要压缩“query-string/index.js”并将其粘贴到你的js底部) - Ronnie Royston
7
为此再额外建立一个图书馆似乎有点过分了…… - The Godfather
8
一个函数使用jQuery过于复杂了,因此你改用了TypeScript、Travis以及其他几个非开发依赖项 :) - Justin Meiners
@JustinMeiners 如果你对这个话题没有有用的贡献,请不要发表评论。这个项目没有使用TypeScript。Travis是一个CI工具,而不是一个依赖项。 - Sindre Sorhus
3
@SindreSorhus 的话有点轻松幽默,但我认为保持对这些事情的复杂性的透视很重要。如果您觉得这没有建设性,那么也一样。 - Justin Meiners

78
使用本地标准的现代方法是使用URLSearchParams。它受到所有主要浏览器的支持,除了IE,但可以使用polyfills available进行兼容处理。
const paramsString = "site.fwx?position=1&archiveid=5000&columns=5&rows=20&sorting=ModifiedTimeAsc"
const searchParams = new URLSearchParams(paramsString);
searchParams.set('rows', 10);
console.log(searchParams.toString()); // return modified string.

1
很好的想法...但是IE完全不支持它,而为这样一个小事情使用polyfill是完全不可行的。 - forsberg
2
这也会对原始的paramsString进行完全的URL编码,因此结果看起来像是site.fwx%3Fposition=1&archiveid=5000&columns=5&rows=10&sorting=ModifiedTimeAsc,这很令人困惑,因为如果你手动构建它,它不会是这样的... - Ben Wheeler
1
希望能看到如何使用它的示例。我的意思是,如何从当前页面获取参数字符串,以及如何在之后设置它。 - The Godfather
4
@Alister的答案有一个错误,new URLSearchParams("site.fwx?position=1&... 应该改为 new URLSearchParams("position=1&... (它只接受搜索字符串,而不是路径)。我已经编辑过来修复了,但是编辑被拒绝了?此外,@the-godfather提供的 const searchParams = new URLSearchParams(location.search); searchParams.set('rows', 10); location.search = searchParams; 是你想要在这个答案中添加的额外信息。 - bazzargh
我最喜欢的解决方案,因为它最短且本地化。你也可以使用 searchParams.get('param') 获取参数。适用于 Node。 - The Onin

61

Ben Alman有一个不错的jquery querystring/url插件在这里,可以轻松地操纵查询字符串。

按照要求 -

进入他的测试页面在这里

在Firebug控制台中输入以下内容

jQuery.param.querystring(window.location.href, 'a=3&newValue=100');

它将返回以下修改后的URL字符串

http://benalman.com/code/test/js-jquery-url-querystring.html?a=3&b=Y&c=Z&newValue=100#n=1&o=2&p=3

请注意查询字符串名称为a的值已从X更改为3,并添加了新值。

您随后可以使用新的url字符串,例如使用document.location = newUrl或更改锚链接等等


4
是不是应该使用jQuery.param.querystring而不是jQuery.queryString? - Petr Peller
13
类型错误:jQuery.param.querystring不是一个函数。 - Tomas
1
为了避免'TypeError'错误,应该使用以下代码:jQuery.queryString(window.location.href, 'a=3&newValue=100') - code-gijoe
2
你应该调用 jQuery.param.querystring。我猜他们已经重构了这个库。 - Will Wu
Ben Alman的jQuery BBQ插件似乎已经被放弃了。我们正在考虑使用Query String,正如被接受的答案中所提到的那样。 - Brylie Christopher Oxley
显示剩余2条评论

40

这是现代更改URL参数的方法:

function setGetParam(key,value) {
  if (history.pushState) {
    var params = new URLSearchParams(window.location.search);
    params.set(key, value);
    var newUrl = window.location.origin 
          + window.location.pathname 
          + '?' + params.toString();
    window.history.pushState({path:newUrl},'',newUrl);
  }
}

3
目前这个解决方案在Internet Explorer 11中不受支持:https://caniuse.com/#search=URLSearchParams - ˈvɔlə
同样的回复在半年前已经被@Alister回答过了。 - FantomX1
1
加油。企业不能决定他们的用户群,很多仍在使用IE11的人是贫困和老年人。这些人正是我们不应该将其归为可接受的破碎体验的人群。 - Dtipson
使用 document.title 作为历史记录标题。 - Amir2mi
4
"Internet Explorer 将于 2022 年 6 月 15 日被淘汰"。请参阅此链接以了解更多信息:https://blogs.windows.com/windowsexperience/2021/05/19/the-future-of-internet-explorer-on-windows-10-is-in-microsoft-edge/。 - Justin Breen
显示剩余3条评论

28

你也可以通过普通的JS来完成它

var url = document.URL
var newAdditionalURL = "";
var tempArray = url.split("?");
var baseURL = tempArray[0];
var aditionalURL = tempArray[1]; 
var temp = "";
if(aditionalURL)
{
var tempArray = aditionalURL.split("&");
for ( var i in tempArray ){
    if(tempArray[i].indexOf("rows") == -1){
            newAdditionalURL += temp+tempArray[i];
                temp = "&";
            }
        }
}
var rows_txt = temp+"rows=10";
var finalURL = baseURL+"?"+newAdditionalURL+rows_txt;

不错!我将其修改为一个函数。你可以发送当前的URL、你要查找的参数名称、新值以及一个布尔值,告诉它如果我在查询字符串中找不到该参数,是否要将参数添加到其中。函数返回修改后的URL。 - Gromer
Gormer,你必须与其他人分享那个函数 :) - Adil Malik
很棒的代码片段。我也将其转换为一个函数以适应我的使用情况。感谢分享!+1 - robabby

23
使用URLSearchParams来检查、获取和设置参数值到URL中。
以下是一个示例,用于获取当前URL,设置新的参数并更新URL或根据您的需求重新加载页面。
var rows = 5; // value that you want to set
var url = new URL(window.location);
(url.searchParams.has('rows') ? url.searchParams.set('rows', rows) : url.searchParams.append('rows', rows));

url.search = url.searchParams;
url        = url.toString();

// if you want to append into URL without reloading the page
history.pushState({}, null, url);

// want to reload the window with a new param
window.location = url;

13

2020年解决方案:如果将nullundefined传递到该值,则设置变量或删除它。

var setSearchParam = function(key, value) {
    if (!window.history.pushState) {
        return;
    }

    if (!key) {
        return;
    }

    var url = new URL(window.location.href);
    var params = new window.URLSearchParams(window.location.search);
    if (value === undefined || value === null) {
        params.delete(key);
    } else {
        params.set(key, value);
    }

    url.search = params;
    url = url.toString();
    window.history.replaceState({url: url}, null, url);
}

请注意,URLSearchParams 在所有主要浏览器的最新版本(2020年)中均无法使用。 - Oliver Schimmer
仍然可以在主要浏览器中使用:https://developer.mozilla.org/zh-CN/docs/Web/API/URLSearchParams,https://googlechrome.github.io/samples/urlsearchparams/index.html - Alper Ebicoglu
1
它在所有主要浏览器中都得到支持,除了IE11:https://caniuse.com/#search=URLSearchParams - Luis Paulo Lohmann
2
即使开始支持,与URLSearchParams相同的答案已经在此问题中至少回答了3次,分别是2017年1月15日15:24回答,2018年6月14日15:54回答和2019年3月1日12:46回答,好像在发布之前没有人阅读回复。 - FantomX1
1
所有的帖子都有一些小问题需要解决。因此,让用户投票并选择最好的一个。 - Alper Ebicoglu
1
为什么需要检查 pushState?是为了检查它是否受支持吗? - M3RS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接