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

ama*_*eur 347 javascript jquery query-string

使用javascript如何在网址中添加查询字符串参数(如果不存在)或是否存在,更新当前值?我正在使用jquery进行客户端开发.

ama*_*eur 457

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

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

  • 当URI中存在哈希时,此答案不起作用 - 查询字符串必须放在哈希值之前,否则它们不会被发送到服务器.http://jsfiddle.net/4yXzR/ (35认同)
  • `[?|&]`应该是`[?&]` (20认同)
  • 这也将处理哈希:https://gist.github.com/niyazpk/f8ac616f181f6042d1e0 (18认同)
  • 通过在分隔符声明之前添加`var`,将分隔符变量作用域限制为局部函数. (8认同)
  • 我想,你应该在第一行添加`value = encodeURIComponent(value);`,否则换行不会正确转义. (3认同)
  • 太好了!@greg:你是对的 - 看看我应该处理哈希标签的变种的答案 (2认同)
  • 有人可以解释为什么这需要 URL 作为参数吗?为什么它返回 URL?比如,这里的用例是什么?类似于`window.location.href = updateQueryStringParameter(window.location.href, 'foo', 'bar')`?为什么不只是`updateQueryStringParameter('foo', 'bar')`? (2认同)

ell*_*ayo 184

我已经扩展了解决方案,并将其与另一个我发现根据用户输入替换/更新/删除查询字符串参数并将URL锚点考虑在内.

不提供值将删除参数,提供一个将添加/更新参数.如果没有提供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, '$1' + key + "=" + value + '$2$3');
        } 
        else {
            hash = url.split('#');
            url = hash[0].replace(re, '$1$3').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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

更新

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

第二次更新

正如@JarónBarends所建议 - Tweak值检查以检查undefined和null以允许设置0值

第三次更新

有一个错误,在hashtag之前直接删除querystring变量会丢失已修复的#标签符号

第四次更新

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

第五次更新

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

  • 只检查`value`的'真实性'会导致它在将值设置为0时从查询字符串中删除变量.所以不要使用`if(value){}`而应使用`if(typeOf value!==') undefined'&& value!== null){}` (5认同)

Ant*_*lin 89

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

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

无论它是否已经存在,现在foo已经确定了bar.

但是,上面的赋值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);
}
Run Code Online (Sandbox Code Playgroud)

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

但是,浏览器支持很差,因为它目前是实验性的,仅在最近版本的Chrome,Firefox,Safari,iOS Safari,Android浏览器,Android Chrome和Opera中使用.用一用填充工具,如果你决定使用它.

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

  • 更新__2019__:现在,除IE和某些小型移动浏览器外,浏览器支持对大多数浏览器都很好。ungap的新的pollyfill很容易涵盖以下内容:https://github.com/ungap/url-search-params (5认同)
  • 我发现 URL 比 URLSearchParams `const url = new URL(window.location); 更容易使用 url.searchParams.set("foo", "bar"); 窗口.location = url;` (4认同)

Gra*_*zan 51

您可以使用浏览器的本机URL API以非常简单的方式执行此操作,其中keyvalue分别是您的参数名称和参数值。

const url = new URL(location.href);
url.searchParams.set(key, value);
Run Code Online (Sandbox Code Playgroud)

这将保留有关 URL 的所有内容,并且仅更改或添加一个查询参数。

然后您可以对该url对象执行任何您想要的操作。例子:

// Log the URL string.
console.log(url.href);

// Go to the URL.
location.assign(url);

// Go to the URL, but overwrite this history entry.
location.replace(url);

// Same as `location.assign` without reloading.
history.pushState(null, '', url);

// Same as `location.replace` without reloading.
history.replaceState(null, '', url);
Run Code Online (Sandbox Code Playgroud)


Ada*_*dam 43

根据@ amateur的答案(现在纳入@j_walker_dev评论中的修复),但考虑到url中有关哈希标记的注释,我使用以下内容:

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

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

编辑:支持删除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, '$1$2');
    } else {
        return uri;
    }
  } else {
    if (uri.match(re)) {
        return uri.replace(re, '$1' + key + "=" + value + '$2');
    } else {
    var hash =  '';
    if( uri.indexOf('#') !== -1 ){
        hash = uri.replace(/.*#/, '#');
        uri = uri.replace(/#.*/, '');
    }
    var separator = uri.indexOf('?') !== -1 ? "&" : "?";    
    return uri + separator + key + "=" + value + hash;
  }
  }  
}
Run Code Online (Sandbox Code Playgroud)

请参阅https://jsfiddle.net/bp3tmuxh/1/

  • 正如在其他答案的评论中指出的那样,`[?|&]`应该只是`[?&]`(否则将匹配`|`). (3认同)
  • 更清洁.对于可以拥有"?"的角度ui-router用户的FYI 在哈希中也是如此.将`var separator`行移到返回的正上方修复了"/ app#/ cool?fun = true"的错误.即使没有真正的查询字符串参数,这也会选择"&"作为分隔符.只有客户. (2认同)

小智 20

这是我的库:https://github.com/Mikhus/jsurl

var u = new Url;
u.query.param='value'; // adds or replaces the param
alert(u)
Run Code Online (Sandbox Code Playgroud)


gli*_*a93 13

现在是 2020 年底,得益于现代 javascript、node.js 和浏览器的支持,我们可以摆脱 3rd 方库漩涡(jquery、query-string 等)和 DRY。

以下是用于添加或更新给定 url 的查询参数的函数的 javascript(node.js) 和 typescript 版本:

Javascript

const getUriWithParam = (baseUrl, params) => {
  const Url = new URL(baseUrl);
  const urlParams = new URLSearchParams(Url.search);
  for (const key in params) {
    if (params[key] !== undefined) {
      urlParams.set(key, params[key]);
    }
  }
  Url.search = urlParams.toString();
  return Url.toString();
};

console.info('expected: https://example.com/?foo=bar');
console.log(getUriWithParam("https://example.com", {foo: "bar"}));

console.info('expected: https://example.com/slug?foo=bar#hash');
console.log(getUriWithParam("https://example.com/slug#hash", {foo: "bar"}));

console.info('expected: https://example.com/?bar=baz&foo=bar');
console.log(getUriWithParam("https://example.com?bar=baz", {foo: "bar"}));

console.info('expected: https://example.com/?foo=baz&bar=baz');
console.log(getUriWithParam("https://example.com?foo=bar&bar=baz", {foo: "baz"}));
Run Code Online (Sandbox Code Playgroud)

打字稿


const getUriWithParam = (
  baseUrl: string,
  params: Record<string, any>
): string => {
  const Url = new URL(baseUrl);
  const urlParams: URLSearchParams = new URLSearchParams(Url.search);
  for (const key in params) {
    if (params[key] !== undefined) {
      urlParams.set(key, params[key]);
    }
  }
  Url.search = urlParams.toString();
  return Url.toString();
};

Run Code Online (Sandbox Code Playgroud)

对于 React Native

URL未在 React Native 中实现。所以你必须事先安装react-native-url-polyfill

对于对象参数

请参阅此答案中的第二个解决方案


Dom*_*c P 11

我意识到这个问题已经过时了,并且已经被解决了,但这是我对它的抨击.我正在尝试重新发明轮子,因为我正在使用当前接受的答案,并且URL片段的错误处理最近让我在一个项目中.

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

更新:我遇到了一个很酷的功能,使用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 + '$1' ) + '=' + 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;
}
Run Code Online (Sandbox Code Playgroud)

  • 这看起来确实不错,可靠的测试用例+使用DOM作为URL解析器。我确实发现了两种情况:http://example.com/?param=val&amp; =&gt; http://example.com/?param=val&amp;&amp;new=key --double&和http://example.com/team = &gt;预期的http://example.com/team?new=key:team /?new = key某些将/ team?new = key重定向到/ team /的查询将丢失。 (2认同)

tra*_*lix 10

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

window.location.search = 'param=value'; // or param=new_value
Run Code Online (Sandbox Code Playgroud)

顺便说一句,这是简单的Javascript.

编辑

您可能想尝试使用jquery query-object插件

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

  • 不过,这不会在 url 上维护任何其他查询字符串参数。 (3认同)

Gal*_*Gal 10

window.location.search是读/写的.

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

如果您尝试执行的操作是维护客户端状态(并且可能使其具有书签功能),则您需要修改URL哈希而不是查询字符串,这会使您保持在同一页面上(window.location.哈希是读/写).这就是twitter.com这样的网站如何做到这一点.

您还需要后退按钮的工作,你就必须结合JavaScript事件到哈希改变事件,一个好的插件是http://benalman.com/projects/jquery-hashchange-plugin/

  • Twitter不再修改哈希!哈希死了,欢迎**历史API**! (3认同)

jak*_*ake 9

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

鉴于URL是http://example.com/?foo=bar&baz#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.

这是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('&');
};
Run Code Online (Sandbox Code Playgroud)


Ada*_*ett 6

这是我的偏好,它涵盖了我能想到的情况.谁能想到一种方法将它减少到一个替换?

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


Fli*_*imm 6

非常简单URLSearchParams,所有现代浏览器都支持(caniuse)。

let p = new URLSearchParams();
p.set("foo", "bar");
p.set("name", "Jack & Jill?");
console.log("http://example.com/?" + p.toString());
Run Code Online (Sandbox Code Playgroud)

如果要修改现有 URL,请像这样构造对象:new URLSearchParams(window.location.search)并将字符串分配给window.location.search


Pao*_*omo 5

我知道这已经很老了,但我想在这里解雇我的工作版本.

function addOrUpdateUrlParam(uri, paramKey, paramVal) {
  var re = new RegExp("([?&])" + paramKey + "=[^&#]*", "i");
  if (re.test(uri)) {
    uri = uri.replace(re, '$1' + paramKey + "=" + paramVal);
  } else {
    var separator = /\?/.test(uri) ? "&" : "?";
    uri = uri + separator + paramKey + "=" + paramVal;
  }
  return uri;
}

jQuery(document).ready(function($) {
  $('#paramKey,#paramValue').on('change', function() {
    if ($('#paramKey').val() != "" && $('#paramValue').val() != "") {
      $('#uri').val(addOrUpdateUrlParam($('#uri').val(), $('#paramKey').val(), $('#paramValue').val()));
    }
  });
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input style="width:100%" type="text" id="uri" value="http://www.example.com/text.php">
<label style="display:block;">paramKey
  <input type="text" id="paramKey">
</label>
<label style="display:block;">paramValue
  <input type="text" id="paramValue">
</label>
Run Code Online (Sandbox Code Playgroud)

注意这是@elreimundo的修改版本