在一个使用AJAX调用的web应用程序中,我需要提交一个请求,但在URL的末尾添加一个参数,例如:

原始URL:

http://server/myapp.php?id=10

导致的网址:

http://server/myapp.php?id=10&enabled=true

寻找一个JavaScript函数,该函数解析URL并查看每个参数,然后添加新参数或更新已经存在的值。


当前回答

Vianney Bajart的答案是正确的;然而,URL只会工作,如果你有完整的URL端口,主机,路径和查询:

new URL('http://server/myapp.php?id=10&enabled=true')

URLSearchParams只会在你只传递查询字符串时起作用:

new URLSearchParams('?id=10&enabled=true')

如果你有一个不完整或相对的URL,不关心的基础URL,你可以通过?获取查询字符串,然后像这样连接:

function setUrlParams(url, key, value) {
  url = url.split('?');
  usp = new URLSearchParams(url[1]);
  usp.set(key, value);
  url[1] = usp.toString();
  return url.join('?');
}

let url = 'myapp.php?id=10';
url = setUrlParams(url, 'enabled', true);  // url = 'myapp.php?id=10&enabled=true'
url = setUrlParams(url, 'id', 11);         // url = 'myapp.php?id=11&enabled=true'

Internet Explorer浏览器不兼容。

其他回答

这将在所有现代浏览器中工作。

function insertParam(key,value) {
      if (history.pushState) {
          var newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?' +key+'='+value;
          window.history.pushState({path:newurl},'',newurl);
      }
    }

查看https://github.com/derek-watson/jsUri

Uri和javascript查询字符串操作。

这个项目结合了Steven Levithan的优秀parseUri正则表达式库。您可以安全地解析所有形状和大小的url,无论它们是多么无效或丑陋。

你需要适应的基本实现是这样的:

function insertParam(key, value) {
    key = encodeURIComponent(key);
    value = encodeURIComponent(value);

    // kvp looks like ['key1=value1', 'key2=value2', ...]
    var kvp = document.location.search.substr(1).split('&');
    let i=0;

    for(; i<kvp.length; i++){
        if (kvp[i].startsWith(key + '=')) {
            let pair = kvp[i].split('=');
            pair[1] = value;
            kvp[i] = pair.join('=');
            break;
        }
    }

    if(i >= kvp.length){
        kvp[kvp.length] = [key,value].join('=');
    }

    // can return this or...
    let params = kvp.join('&');

    // reload page with new params
    document.location.search = params;
}

这大约是正则表达式或基于搜索的解决方案的两倍,但这完全取决于查询字符串的长度和任何匹配的索引


为了完成起见,我以慢速regex方法为基准(大约慢了150%)

function insertParam2(key,value)
{
    key = encodeURIComponent(key); value = encodeURIComponent(value);

    var s = document.location.search;
    var kvp = key+"="+value;

    var r = new RegExp("(&|\\?)"+key+"=[^\&]*");

    s = s.replace(r,"$1"+kvp);

    if(!RegExp.$1) {s += (s.length>0 ? '&' : '?') + kvp;};

    //again, do what you will here
    document.location.search = s;
}

这是一个添加查询参数的简单方法:

const query = new URLSearchParams(window.location.search);
query.append("enabled", "true");

这就是这里更多的内容。

请注意支持规格。

我添加我的解决方案,因为它支持相对url除了绝对url。在其他方面,它与顶部的答案相同,后者也使用Web API。

/**
 * updates a relative or absolute
 * by setting the search query with
 * the passed key and value.
 */
export const setQueryParam = (url, key, value) => {
  const dummyBaseUrl = 'https://dummy-base-url.com';
  const result = new URL(url, dummyBaseUrl);
  result.searchParams.set(key, value);
  return result.toString().replace(dummyBaseUrl, '');
};

还有人开玩笑说:

// some jest tests
describe('setQueryParams', () => {
  it('sets param on relative url with base path', () => {
    // act
    const actual = setQueryParam(
      '/', 'ref', 'some-value',
    );
    // assert
    expect(actual).toEqual('/?ref=some-value');
  });
  it('sets param on relative url with no path', () => {
    // act
    const actual = setQueryParam(
      '', 'ref', 'some-value',
    );
    // assert
    expect(actual).toEqual('/?ref=some-value');
  });
  it('sets param on relative url with some path', () => {
    // act
    const actual = setQueryParam(
      '/some-path', 'ref', 'some-value',
    );
    // assert
    expect(actual).toEqual('/some-path?ref=some-value');
  });
  it('overwrites existing param', () => {
    // act
    const actual = setQueryParam(
      '/?ref=prev-value', 'ref', 'some-value',
    );
    // assert
    expect(actual).toEqual('/?ref=some-value');
  });
  it('sets param while another param exists', () => {
    // act
    const actual = setQueryParam(
      '/?other-param=other-value', 'ref', 'some-value',
    );
    // assert
    expect(actual).toEqual('/?other-param=other-value&ref=some-value');
  });
  it('honors existing base url', () => {
    // act
    const actual = setQueryParam(
      'https://base.com', 'ref', 'some-value',
    );
    // assert
    expect(actual).toEqual('https://base.com/?ref=some-value');
  });
  it('honors existing base url with some path', () => {
    // act
    const actual = setQueryParam(
      'https://base.com/some-path', 'ref', 'some-value',
    );
    // assert
    expect(actual).toEqual('https://base.com/some-path?ref=some-value');
  });
});