Javascript 如何添加或更新查询字符串参数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5999118/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 19:48:44  来源:igfitidea点击:

How can I add or update a query string parameter?

javascriptjqueryquery-string

提问by amateur

With javascript how can I add a query string parameter to the url if not present or if it present, update the current value? I am using jquery for my client side development.

使用 javascript 如何将查询字符串参数添加到 url 如果不存在或如果存在,则更新当前值?我正在使用 jquery 进行客户端开发。

回答by amateur

I wrote the following function which accomplishes what I want to achieve:

我编写了以下函数来完成我想要实现的目标:

function updateQueryStringParameter(uri, key, value) {
  var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
  var separator = uri.indexOf('?') !== -1 ? "&" : "?";
  if (uri.match(re)) {
    return uri.replace(re, '' + key + "=" + value + '');
  }
  else {
    return uri + separator + key + "=" + value;
  }
}

回答by ellemayo

I have expanded the solution and combined it with another that I found to replace/update/remove the querystring parameters based on the users input and taking the urls anchor into consideration.

我扩展了该解决方案并将其与我发现的另一个解决方案相结合,以根据用户输入替换/更新/删除查询字符串参数并考虑 urls 锚点。

Not supplying a value will remove the parameter, supplying one will add/update the parameter. If no URL is supplied, it will be grabbed from window.location

不提供值将删除参数,提供一个将添加/更新参数。如果没有提供 URL,它将从 window.location 抓取

function UpdateQueryString(key, value, url) {
    if (!url) url = window.location.href;
    var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi"),
        hash;

    if (re.test(url)) {
        if (typeof value !== 'undefined' && value !== null) {
            return url.replace(re, '' + key + "=" + value + '');
        } 
        else {
            hash = url.split('#');
            url = hash[0].replace(re, '').replace(/(&|\?)$/, '');
            if (typeof hash[1] !== 'undefined' && hash[1] !== null) {
                url += '#' + hash[1];
            }
            return url;
        }
    }
    else {
        if (typeof value !== 'undefined' && value !== null) {
            var separator = url.indexOf('?') !== -1 ? '&' : '?';
            hash = url.split('#');
            url = hash[0] + separator + key + '=' + value;
            if (typeof hash[1] !== 'undefined' && hash[1] !== null) {
                url += '#' + hash[1];
            }
            return url;
        }
        else {
            return url;
        }
    }
}

Update

更新

There was a bug when removing the first parameter in the querystring, I have reworked the regex and test to include a fix.

删除查询字符串中的第一个参数时出现错误,我重新编写了正则表达式并进行了测试以包含修复程序。

Second Update

第二次更新

As suggested by @JarónBarends - Tweak value check to check against undefined and null to allow setting 0 values

正如@JarónBarends 所建议的那样 - 调整值检查以检查 undefined 和 null 以允许设置 0 值

Third Update

第三次更新

There was a bug where removing a querystring variable directly before a hashtag would lose the hashtag symbol which has been fixed

有一个错误,即在主题标签之前直接删除查询字符串变量会丢失已修复的主题标签符号

Fourth Update

第四次更新

Thanks @rooby for pointing out a regex optimization in the first RegExp object. Set initial regex to ([?&]) due to issue with using (\?|&) found by @YonatanKarni

感谢@rooby 指出第一个 RegExp 对象中的正则表达式优化。由于使用@YonatanKarni 发现的 (\?|&) 问题,将初始正则表达式设置为 ([?&])

Fifth Update

第五次更新

Removing declaring hash var in if/else statement

删除 if/else 语句中声明的哈希变量

回答by Anthony Manning-Franklin

The URLSearchParamsutility can be useful for this in combination with window.location.search. For example:

URLSearchParams实用程序可以与组合是这个有用的window.location.search。例如:

if ('URLSearchParams' in window) {
    var searchParams = new URLSearchParams(window.location.search);
    searchParams.set("foo", "bar");
    window.location.search = searchParams.toString();
}

Now foohas been set to barregardless of whether or not it already existed.

Nowfoo已经设置为bar不管它是否已经存在。

However, the above assignment to window.location.searchwill cause a page load, so if that's not desirable use the History APIas follows:

但是,上面的赋值window.location.search将导致页面加载,所以如果这不是可取的,请使用History API,如下所示:

if ('URLSearchParams' in window) {
    var searchParams = new URLSearchParams(window.location.search)
    searchParams.set("foo", "bar");
    var newRelativePathQuery = window.location.pathname + '?' + searchParams.toString();
    history.pushState(null, '', newRelativePathQuery);
}

Now you don't need to write your own regex or logic to handle the possible existence of query strings.

现在您无需编写自己的正则表达式或逻辑来处理可能存在的查询字符串。

However, browser supportis poor as it's currently experimental and only in use in recent versions of Chrome, Firefox, Safari, iOS Safari, Android Browser, Android Chrome and Opera. Use with a polyfillif you do decide to use it.

然而,浏览器支持很差,因为它目前处于实验阶段,仅在最新版本的 Chrome、Firefox、Safari、iOS Safari、Android 浏览器、Android Chrome 和 Opera 中使用。如果您决定使用polyfill,请与polyfill一起使用。

Update:Browser support has improved since my original answer.

更新:自从我的原始答案以来,浏览器支持有所改善。

回答by Adam

Based on @amateur's answer (and now incorporating the fix from @j_walker_dev comment), but taking into account the comment about hash tags in the url I use the following:

基于@amateur 的回答(现在结合了@j_walker_dev 评论中的修复),但考虑到关于 url 中哈希标签的评论,我使用以下内容:

function updateQueryStringParameter(uri, key, value) {
  var re = new RegExp("([?&])" + key + "=.*?(&|#|$)", "i");
  if (uri.match(re)) {
    return uri.replace(re, '' + key + "=" + value + '');
  } else {
    var hash =  '';
    if( uri.indexOf('#') !== -1 ){
        hash = uri.replace(/.*#/, '#');
        uri = uri.replace(/#.*/, '');
    }
    var separator = uri.indexOf('?') !== -1 ? "&" : "?";    
    return uri + separator + key + "=" + value + hash;
  }
}

Edited to fix [?|&]in regex which should of course be [?&]as pointed out in the comments

编辑以修复[?|&]正则表达式,这当然应该[?&]在评论中指出

Edit: Alternative version to support removing URL params as well. I have used value === undefinedas the way to indicate removal. Could use value === falseor even a separate input param as wanted.

编辑:支持删除 URL 参数的替代版本。我已用作value === undefined表示移除的方式。可以根据需要使用value === false甚至单独的输入参数。

function updateQueryStringParameter(uri, key, value) {
  var re = new RegExp("([?&])" + key + "=.*?(&|#|$)", "i");
  if( value === undefined ) {
    if (uri.match(re)) {
        return uri.replace(re, '');
    } else {
        return uri;
    }
  } else {
    if (uri.match(re)) {
        return uri.replace(re, '' + key + "=" + value + '');
    } else {
    var hash =  '';
    if( uri.indexOf('#') !== -1 ){
        hash = uri.replace(/.*#/, '#');
        uri = uri.replace(/#.*/, '');
    }
    var separator = uri.indexOf('?') !== -1 ? "&" : "?";    
    return uri + separator + key + "=" + value + hash;
  }
  }  
}

See it in action at https://jsfiddle.net/bp3tmuxh/1/

https://jsfiddle.net/bp3tmuxh/1/查看它的实际效果

回答by Mikhus

Here is my library to do that: https://github.com/Mikhus/jsurl

这是我的图书馆:https: //github.com/Mikhus/jsurl

var u = new Url;
u.query.param='value'; // adds or replaces the param
alert(u)

回答by tradyblix

If it's not set or want to update with a new value you can use:

如果未设置或想要使用新值更新,您可以使用:

window.location.search = 'param=value'; // or param=new_value

This is in simple Javascript, by the way.

顺便说一下,这是在简单的 Javascript 中。

EDIT

编辑

You may want to try using the jquery query-objectplugin

您可能想尝试使用 jquery查询对象插件

window.location.search = jQuery.query.set("param", 5);

window.location.search = jQuery.query.set("param", 5);

回答by Gal

window.location.search is read/write.

window.location.search 是读/写。

However - modifying the query string will redirect the page you're on and cause a refresh from the server.

但是 - 修改查询字符串将重定向您所在的页面并导致服务器刷新。

If what you're attempting to do is maintain client side state (and potentially make it bookmark-able), you'll want to modify the URL hash instead of the query string, which keeps you on the same page (window.location.hash is read/write). This is how web sites like twitter.com do this.

如果您试图做的是维护客户端状态(并可能使其成为书签),您将需要修改 URL 哈希而不是查询字符串,这使您保持在同一页面 (window.location.哈希是读/写)。这就是 twitter.com 等网站的做法。

You'll also want the back button to work, you'll have to bind javascript events to the hash change event, a good plugin for that is http://benalman.com/projects/jquery-hashchange-plugin/

您还需要后退按钮工作,您必须将 javascript 事件绑定到哈希更改事件,一个很好的插件是http://benalman.com/projects/jquery-hashchange-plugin/

回答by Dominic P

I realize this question is old and has been answered to death, but here's my stab at it. I'm trying to reinvent the wheel here because I was using the currently accepted answer and the mishandling of URL fragments recently bit me in a project.

我意识到这个问题已经过时了并且已经得到了死亡的回答,但这是我的尝试。我试图在这里重新发明轮子,因为我使用的是当前接受的答案,而最近在一个项目中对 URL 片段的错误处理让我感到困惑。

The function is below. It's quite long, but it was made to be as resilient as possible. I would love suggestions for shortening/improving it. I put together a small jsFiddle test suitefor it (or other similar functions). If a function can pass every one of the tests there, I say it's probably good to go.

功能如下。它很长,但它尽可能地具有弹性。我喜欢缩短/改进它的建议。我为它(或其他类似的功能)组合了一个小的jsFiddle 测试套件。如果一个函数可以通过那里的所有测试,我说它可能很好。

Update:I came across a cool function for using the DOM to parse URLs, so I incorporated that technique here. It makes the function shorter and more reliable. Props to the author of that function.

更新:我遇到了一个使用 DOM 解析 URL的很酷的函数,所以我在这里合并了该技术。它使功能更短,更可靠。向该函数的作者提供道具。

/**
 * Add or update a query string parameter. If no URI is given, we use the current
 * window.location.href value for the URI.
 * 
 * Based on the DOM URL parser described here:
 * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/
 *
 * @param   (string)    uri     Optional: The URI to add or update a parameter in
 * @param   (string)    key     The key to add or update
 * @param   (string)    value   The new value to set for key
 *
 * Tested on Chrome 34, Firefox 29, IE 7 and 11
 */
function update_query_string( uri, key, value ) {

    // Use window URL if no query string is provided
    if ( ! uri ) { uri = window.location.href; }

    // Create a dummy element to parse the URI with
    var a = document.createElement( 'a' ), 

        // match the key, optional square brackets, an equals sign or end of string, the optional value
        reg_ex = new RegExp( key + '((?:\[[^\]]*\])?)(=|$)(.*)' ),

        // Setup some additional variables
        qs,
        qs_len,
        key_found = false;

    // Use the JS API to parse the URI 
    a.href = uri;

    // If the URI doesn't have a query string, add it and return
    if ( ! a.search ) {

        a.search = '?' + key + '=' + value;

        return a.href;
    }

    // Split the query string by ampersands
    qs = a.search.replace( /^\?/, '' ).split( /&(?:amp;)?/ );
    qs_len = qs.length; 

    // Loop through each query string part
    while ( qs_len > 0 ) {

        qs_len--;

        // Remove empty elements to prevent double ampersands
        if ( ! qs[qs_len] ) { qs.splice(qs_len, 1); continue; }

        // Check if the current part matches our key
        if ( reg_ex.test( qs[qs_len] ) ) {

            // Replace the current value
            qs[qs_len] = qs[qs_len].replace( reg_ex, key + '' ) + '=' + value;

            key_found = true;
        }
    }   

    // If we haven't replaced any occurrences above, add the new parameter and value
    if ( ! key_found ) { qs.push( key + '=' + value ); }

    // Set the new query string
    a.search = '?' + qs.join( '&' );

    return a.href;
}

回答by jake

Here's my approach: The location.params()function (shown below) can be used as a getter or setter. Examples:

这是我的方法:该location.params()函数(如下所示)可以用作 getter 或 setter。例子:

Given the URL is http://example.com/?foo=bar&baz#some-hash,

鉴于 URL 是http://example.com/?foo=bar&baz#some-hash

  1. location.params()will return an object with all the query parameters: {foo: 'bar', baz: true}.
  2. location.params('foo')will return 'bar'.
  3. location.params({foo: undefined, hello: 'world', test: true})will change the URL to http://example.com/?baz&hello=world&test#some-hash.
  1. location.params()会返回一个对象所有的查询参数:{foo: 'bar', baz: true}
  2. location.params('foo')会回来'bar'
  3. location.params({foo: undefined, hello: 'world', test: true})将 URL 更改为http://example.com/?baz&hello=world&test#some-hash.

Here is the params()function, which can optionally be assigned to the window.locationobject.

这是params()函数,可以选择将其分配给window.location对象。

location.params = function(params) {
  var obj = {}, i, parts, len, key, value;

  if (typeof params === 'string') {
    value = location.search.match(new RegExp('[?&]' + params + '=?([^&]*)[&#$]?'));
    return value ? value[1] : undefined;
  }

  var _params = location.search.substr(1).split('&');

  for (i = 0, len = _params.length; i < len; i++) {
    parts = _params[i].split('=');
    if (! parts[0]) {continue;}
    obj[parts[0]] = parts[1] || true;
  }

  if (typeof params !== 'object') {return obj;}

  for (key in params) {
    value = params[key];
    if (typeof value === 'undefined') {
      delete obj[key];
    } else {
      obj[key] = value;
    }
  }

  parts = [];
  for (key in obj) {
    parts.push(key + (obj[key] === true ? '' : '=' + obj[key]));
  }

  location.search = parts.join('&');
};

回答by Adam Leggett

This is my preference, and it covers the cases I can think of. Can anyone think of a way to reduce it to a single replace?

这是我的偏好,它涵盖了我能想到的情况。任何人都可以想出一种方法将其减少为单个替换吗?

function setParam(uri, key, val) {
    return uri
        .replace(RegExp("([?&]"+key+"(?=[=&#]|$)[^#&]*|(?=#|$))"), "&"+key+"="+encodeURIComponent(val))
        .replace(/^([^?&]+)&/, "?");
}