在一个使用AJAX调用的web应用程序中,我需要提交一个请求,但在URL的末尾添加一个参数,例如:
原始URL:
http://server/myapp.php?id=10
导致的网址:
http://server/myapp.php?id=10&enabled=true
寻找一个JavaScript函数,该函数解析URL并查看每个参数,然后添加新参数或更新已经存在的值。
在一个使用AJAX调用的web应用程序中,我需要提交一个请求,但在URL的末尾添加一个参数,例如:
原始URL:
http://server/myapp.php?id=10
导致的网址:
http://server/myapp.php?id=10&enabled=true
寻找一个JavaScript函数,该函数解析URL并查看每个参数,然后添加新参数或更新已经存在的值。
当前回答
这就是我在服务器端(如Node.js)添加或更新一些基本url参数时使用的方法。
CoffeScript:
### @method addUrlParam Adds parameter to a given url. If the parameter already exists in the url is being replaced. @param {string} url @param {string} key Parameter's key @param {string} value Parameter's value @returns {string} new url containing the parameter ### addUrlParam = (url, key, value) -> newParam = key+"="+value result = url.replace(new RegExp('(&|\\?)' + key + '=[^\&|#]*'), '$1' + newParam) if result is url result = if url.indexOf('?') != -1 then url.split('?')[0] + '?' + newParam + '&' + url.split('?')[1] else if url.indexOf('#') != -1 then url.split('#')[0] + '?' + newParam + '#' + url.split('#')[1] else url + '?' + newParam return result
JavaScript:
function addUrlParam(url, key, value) { var newParam = key+"="+value; var result = url.replace(new RegExp("(&|\\?)"+key+"=[^\&|#]*"), '$1' + newParam); if (result === url) { result = (url.indexOf("?") != -1 ? url.split("?")[0]+"?"+newParam+"&"+url.split("?")[1] : (url.indexOf("#") != -1 ? url.split("#")[0]+"?"+newParam+"#"+ url.split("#")[1] : url+'?'+newParam)); } return result; } var url = "http://www.example.com?foo=bar&ciao=3&doom=5#hashme"; result1.innerHTML = addUrlParam(url, "ciao", "1"); <p id="result1"></p>
其他回答
此解决方案使用更新的搜索参数更新窗口的当前URL,而无需实际重新加载页面。这种方法在PWA/SPA上下文中很有用。
function setURLSearchParam(key, value) {
const url = new URL(window.location.href);
url.searchParams.set(key, value);
window.history.pushState({ path: url.href }, '', url.href);
}
你需要适应的基本实现是这样的:
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;
}
好的,在这里我比较两个函数,一个由我自己(regExp)和另一个由(annakata)。
将数组:
function insertParam(key, value)
{
key = escape(key); value = escape(value);
var kvp = document.location.search.substr(1).split('&');
var i=kvp.length; var x; while(i--)
{
x = kvp[i].split('=');
if (x[0]==key)
{
x[1] = value;
kvp[i] = x.join('=');
break;
}
}
if(i<0) {kvp[kvp.length] = [key,value].join('=');}
//this will reload the page, it's likely better to store this until finished
return "&"+kvp.join('&');
}
正则表达式的方法:
function addParameter(param, value)
{
var regexp = new RegExp("(\\?|\\&)" + param + "\\=([^\\&]*)(\\&|$)");
if (regexp.test(document.location.search))
return (document.location.search.toString().replace(regexp, function(a, b, c, d)
{
return (b + param + "=" + value + d);
}));
else
return document.location.search+ param + "=" + value;
}
测试用例:
time1=(new Date).getTime();
for (var i=0;i<10000;i++)
{
addParameter("test","test");
}
time2=(new Date).getTime();
for (var i=0;i<10000;i++)
{
insertParam("test","test");
}
time3=(new Date).getTime();
console.log((time2-time1)+" "+(time3-time2));
似乎即使使用最简单的解决方案(当regexp只使用test而不输入.replace函数时),它仍然比分裂要慢…好。Regexp有点慢,但是…喔…
在URL类中有一个内置函数,你可以使用它来轻松处理查询字符串的键/值参数:
const url = new URL(window.location.href);
// url.searchParams has several function, we just use `set` function
// to set a value, if you just want to append without replacing value
// let use `append` function
url.searchParams.set('key', 'value');
console.log(url.search) // <== '?key=value'
// if window.location.href has already some qs params this `set` function
// modify or append key/value in it
有关searchParams函数的更多信息。
IE不支持URL,请检查兼容性
就我所知,上面的答案都没有解决查询字符串包含参数的情况,这些参数本身就是一个数组,因此会出现不止一次,例如:
http://example.com?sizes[]=a&sizes[]=b
下面的函数是我用来更新document.location.search的。它接受一个键/值对数组作为参数,它将返回一个修改后的版本,你可以做任何你想做的事情。我是这样使用的:
var newParams = [
['test','123'],
['best','456'],
['sizes[]','XXL']
];
var newUrl = document.location.pathname + insertParams(newParams);
history.replaceState('', '', newUrl);
如果当前url为:
http://example.com/index.php?test=replaceme&sizes [] = XL
这会让你
http://example.com/index.php?test=123&sizes[]=XL&尺寸[]=XXL&best=456
函数
function insertParams(params) {
var result;
var ii = params.length;
var queryString = document.location.search.substr(1);
var kvps = queryString ? queryString.split('&') : [];
var kvp;
var skipParams = [];
var i = kvps.length;
while (i--) {
kvp = kvps[i].split('=');
if (kvp[0].slice(-2) != '[]') {
var ii = params.length;
while (ii--) {
if (params[ii][0] == kvp[0]) {
kvp[1] = params[ii][1];
kvps[i] = kvp.join('=');
skipParams.push(ii);
}
}
}
}
var ii = params.length;
while (ii--) {
if (skipParams.indexOf(ii) === -1) {
kvps.push(params[ii].join('='));
}
}
result = kvps.length ? '?' + kvps.join('&') : '';
return result;
}