我如何添加或更新查询string参数?
使用JavaScript我怎么能添加一个查询string参数的URL如果不存在或如果它存在,更新当前值? 我正在使用jquery进行我的客户端开发。
我写了下面的函数来完成我想实现的function:
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; } }
我已经扩大了解决scheme,并将其与另一个结合,我发现取代/更新/删除基于用户input的查询string参数,并考虑到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; } }
UPDATE
删除查询string中的第一个参数时出现了一个错误,我重写了正则expression式,并testing以包含修复。
第二次更新
正如@JarónBarends所build议的那样 – 调整值检查以检查未定义的和空值以允许设置0值
第三次更新
有一个错误,就是在hashtag会丢失已经修复的hashtag符号之前直接删除一个querystringvariables
第四次更新
感谢@rooby在第一个RegExp对象中指出正则expression式优化。 由于使用@YonatanKarni发现的(\?|&),将初始正则expression式设置为([?&])
第五次更新
删除if / else语句中的声明散列var
基于@业余的答案(现在整合来自@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; } }
编辑修正[?|&]
在正则expression式当然应该[?&]
在评论中指出
编辑:替代版本以支持删除url参数。 我已经使用value === undefined
作为指示删除的方式。 可以value === false
,甚至是一个单独的input参数想要的。
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; } } }
这是我的图书馆做到这一点: https : //github.com/Mikhus/jsurl
var u = new Url; u.query.param='value'; // adds or replaces the param alert(u)
URLSearchParams实用程序可以与window.location.search
结合使用。 例如:
if ('URLSearchParams' in window) { var searchParams = new URLSearchParams(window.location.search); searchParams.set("foo", "bar"); window.location.search = searchParams.toString(); }
现在foo
已经被设置为bar
不pipe它是否已经存在。
但是,上面的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); }
现在,您不需要编写自己的正则expression式或逻辑来处理查询string的可能存在。
但是, 浏览器支持很差,因为它目前是实验性的,只能在最近版本的Chrome,Firefox,Safari,iOS Safari,Android Browser,Android Chrome和Opera中使用。 如果您决定使用它,请使用polyfill 。
更新:自从我原来的答案以来,浏览器支持已经得到改善
window.location.search是可读/写的。
但是,修改查询string将redirect您所在的页面,并从服务器进行刷新。
如果你试图做的是保持客户端状态(并且可能使其具有书签能力),那么你将需要修改URL哈希而不是查询string,这使得你在同一页面(window.location)。散列是读/写)。 这是像twitter.com这样的网站做到这一点。
你也想要后退button的工作,你将不得不把javascript事件绑定到哈希变化事件,一个很好的插件是http://benalman.com/projects/jquery-hashchange-plugin/
这是我的方法: location.params()
函数(如下所示)可以用作getter或setter。 例子:
鉴于url是http://example.com/?foo=bar&baz#some-hash
,
-
location.params()
将返回一个包含所有查询参数的对象:{foo: 'bar', baz: true}
。 -
location.params('foo')
将返回'bar'
。 -
location.params({foo: undefined, hello: 'world', test: true})
会将url更改为http://example.com/?baz&hello=world&test#some-hash
。
这里是params()
函数,它可以有select地分配给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('&'); };
如果没有设置或者想用新的值更新,你可以使用:
window.location.search = 'param=value'; // or param=new_value
顺便说一句,这是简单的Javascript。
编辑
您可能想尝试使用jQuery 查询对象插件
window.location.search = jQuery.query.set(“param”,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())); } }); });
<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>
这是我的偏好,涵盖了我能想到的情况。 任何人都可以想办法将其减less到一个单一的替代?
function setParam(uri, key, val) { return uri .replace(RegExp("([?&]"+key+"(?=[=&#]|$)[^#&]*|(?=#|$))"), "&"+key+"="+encodeURIComponent(val)) .replace(/^([^?&]+)&/, "$1?"); }
我意识到这个问题是古老的,已经回答了死亡,但这里是我的刺伤。 我试图在这里重新发明轮子,因为我正在使用当前接受的答案,最近URL片段的error handling在一个项目中占据了我的位置。
function如下。 这是相当长的,但它是尽可能有弹性。 我很乐意提出缩短/改进的build议。 我为它(或其他类似的function)组装了一个小型的jsFiddletesting套件 。 如果一个函数可以通过每一个testing,我认为这可能是一件好事。
更新:我遇到了一个很酷的函数来使用DOMparsingURL ,所以我在这里引入了这个技巧。 它使function更短,更可靠。 支持该function的作者。
/** * 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 bracktes, 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--; // 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 occurences 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; }
我从这里拿(兼容“严格使用”;并不真正使用jQuery):
function decodeURIParams(query) { if (query == null) query = window.location.search; if (query[0] == '?') query = query.substring(1); var params = query.split('&'); var result = {}; for (var i = 0; i < params.length; i++) { var param = params[i]; var pos = param.indexOf('='); if (pos >= 0) { var key = decodeURIComponent(param.substring(0, pos)); var val = decodeURIComponent(param.substring(pos + 1)); result[key] = val; } else { var key = decodeURIComponent(param); result[key] = true; } } return result; } function encodeURIParams(params, addQuestionMark) { var pairs = []; for (var key in params) if (params.hasOwnProperty(key)) { var value = params[key]; if (value != null) /* matches null and undefined */ { pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)) } } if (pairs.length == 0) return ''; return (addQuestionMark ? '?' : '') + pairs.join('&'); } //// alternative to $.extend if not using jQuery: // function mergeObjects(destination, source) { // for (var key in source) if (source.hasOwnProperty(key)) { // destination[key] = source[key]; // } // return destination; // } function navigateWithURIParams(newParams) { window.location.search = encodeURIParams($.extend(decodeURIParams(), newParams), true); }
用法示例:
// add/update parameters navigateWithURIParams({ foo: 'bar', boz: 42 }); // remove parameter navigateWithURIParams({ foo: null }); // submit the given form by adding/replacing URI parameters (with jQuery) $('.filter-form').submit(function(e) { e.preventDefault(); navigateWithURIParams(decodeURIParams($(this).serialize())); });
基于@ellemayo给出的答案,我提出了以下解决scheme,允许在需要时禁用哈希标记:
function updateQueryString(key, value, options) { if (!options) options = {}; var url = options.url || location.href; var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi"), hash; hash = url.split('#'); url = hash[0]; if (re.test(url)) { if (typeof value !== 'undefined' && value !== null) { url = url.replace(re, '$1' + key + "=" + value + '$2$3'); } else { url = url.replace(re, '$1$3').replace(/(&|\?)$/, ''); } } else if (typeof value !== 'undefined' && value !== null) { var separator = url.indexOf('?') !== -1 ? '&' : '?'; url = url + separator + key + '=' + value; } if ((typeof options.hash === 'undefined' || options.hash) && typeof hash[1] !== 'undefined' && hash[1] !== null) url += '#' + hash[1]; return url; }
像这样调用它:
updateQueryString('foo', 'bar', { url: 'http://my.example.com#hash', hash: false });
结果是:
http://my.example.com?foo=bar
这是一个较短的版本,照顾
- 查询有或没有给定的参数
- 查询多个参数值
- 包含散列的查询
码:
var setQueryParameter = function(uri, key, value) { var re = new RegExp("([?&])("+ key + "=)[^&#]*", "g"); if (uri.match(re)) return uri.replace(re, '$1$2' + value); // need to add parameter to URI var paramString = (uri.indexOf('?') < 0 ? "?" : "&") + key + "=" + value; var hashIndex = uri.indexOf('#'); if (hashIndex < 0) return uri + paramString; else return uri.substring(0, hashIndex) + paramString + uri.substring(hashIndex); }
正则expression式的描述可以在这里find。
注 :这个解决scheme是基于@amateur的答案,但有很多改进。
不使用正则expression式的另一种方法。 支持URL末尾的“散列”锚点以及多个问号字符(?)。 应该比正则expression式方法稍微快一点。
function setUrlParameter(url, key, value) { var parts = url.split("#", 2), anchor = parts.length > 1 ? "#" + parts[1] : ''; var query = (url = parts[0]).split("?", 2); if (query.length === 1) return url + "?" + key + "=" + value + anchor; for (var params = query[query.length - 1].split("&"), i = 0; i < params.length; i++) if (params[i].toLowerCase().startsWith(key.toLowerCase() + "=")) return params[i] = key + "=" + value, query[query.length - 1] = params.join("&"), query.join("?") + anchor; return url + "&" + key + "=" + value + anchor }
给Gal和tradyblixbuild议修改window.location.search
的代码示例:
var qs = window.location.search || "?"; var param = key + "=" + value; // remember to URI encode your parameters if (qs.length > 1) { // more than just the question mark, so append with ampersand qs = qs + "&"; } qs = qs + param; window.location.search = qs;
Java脚本代码查找特定查询string并replace其值*
('input.letter').click(function () { //0- prepare values var qsTargeted = 'letter=' + this.value; //"letter=A"; var windowUrl = ''; var qskey = qsTargeted.split('=')[0]; var qsvalue = qsTargeted.split('=')[1]; //1- get row url var originalURL = window.location.href; //2- get query string part, and url if (originalURL.split('?').length > 1) //qs is exists { windowUrl = originalURL.split('?')[0]; var qs = originalURL.split('?')[1]; //3- get list of query strings var qsArray = qs.split('&'); var flag = false; //4- try to find query string key for (var i = 0; i < qsArray.length; i++) { if (qsArray[i].split('=').length > 0) { if (qskey == qsArray[i].split('=')[0]) { //exists key qsArray[i] = qskey + '=' + qsvalue; flag = true; break; } } } if (!flag)// //5- if exists modify,else add { qsArray.push(qsTargeted); } var finalQs = qsArray.join('&'); //6- prepare final url window.location = windowUrl + '?' + finalQs; } else { //6- prepare final url //add query string window.location = originalURL + '?' + qsTargeted; } }) });
是的,我有一个问题,我的querystring会溢出和重复,但这是由于我自己的低迷。 所以我玩了一些jQuery的jQuery(真正的Sizzle)和C#的魔术。
所以我才意识到,在服务器完成了传递的值之后,这些值不再重复,没有重用,如果客户想要做同样的事情,显然它将永远是一个新的请求,即使它的传递相同的参数。 而这就是所有的客户,所以一些caching/cookies等在这方面可能很酷。
JS:
$(document).ready(function () { $('#ser').click(function () { SerializeIT(); }); function SerializeIT() { var baseUrl = ""; baseUrl = getBaseUrlFromBrowserUrl(window.location.toString()); var myQueryString = ""; funkyMethodChangingStuff(); //whatever else before serializing and creating the querystring myQueryString = $('#fr2').serialize(); window.location.replace(baseUrl + "?" + myQueryString); } function getBaseUrlFromBrowserUrl(szurl) { return szurl.split("?")[0]; } function funkyMethodChangingStuff(){ //do stuff to whatever is in fr2 } });
HTML:
<div id="fr2"> <input type="text" name="qURL" value="http://somewhere.com" /> <input type="text" name="qSPart" value="someSearchPattern" /> </div> <button id="ser">Serialize! and go play with the server.</button>
C#:
using System.Web; using System.Text; using System.Collections.Specialized; public partial class SomeCoolWebApp : System.Web.UI.Page { string weburl = string.Empty; string partName = string.Empty; protected void Page_Load(object sender, EventArgs e) { string loadurl = HttpContext.Current.Request.RawUrl; string querySZ = null; int isQuery = loadurl.IndexOf('?'); if (isQuery == -1) { //If There Was no Query } else if (isQuery >= 1) { querySZ = (isQuery < loadurl.Length - 1) ? loadurl.Substring(isQuery + 1) : string.Empty; string[] getSingleQuery = querySZ.Split('?'); querySZ = getSingleQuery[0]; NameValueCollection qs = null; qs = HttpUtility.ParseQueryString(querySZ); weburl = qs["qURL"]; partName = qs["qSPart"]; //call some great method thisPageRocks(weburl,partName); or whatever. } } }
好的批评是受欢迎的(这是一个夜间调酒,所以随时注意调整)。 如果这有帮助,大拇指,快乐编码。
没有重复,每个请求都像你一样修改它,并且由于这个结构是如何的,所以很容易从这个dom中dynamic地添加更多的查询。
以下是使用锚定HTML元素的内置属性的另一种方法:
- 处理多值参数。
- 没有修改#片段或查询string本身以外的任何风险。
- 可能会更容易阅读? 但时间更长。
var a = document.createElement('a'), getHrefWithUpdatedQueryString = function(param, value) { return updatedQueryString(window.location.href, param, value); }, updatedQueryString = function(url, param, value) { /* A function which modifies the query string by setting one parameter to a single value. Any other instances of parameter will be removed/replaced. */ var fragment = encodeURIComponent(param) + '=' + encodeURIComponent(value); a.href = url; if (a.search.length === 0) { a.search = '?' + fragment; } else { var didReplace = false, // Remove leading '?' parts = a.search.substring(1) // Break into pieces .split('&'), reassemble = [], len = parts.length; for (var i = 0; i < len; i++) { var pieces = parts[i].split('='); if (pieces[0] === param) { if (!didReplace) { reassemble.push('&' + fragment); didReplace = true; } } else { reassemble.push(parts[i]); } } if (!didReplace) { reassemble.push('&' + fragment); } a.search = reassemble.join('&'); } return a.href; };
如果你想一次设置多个参数:
function updateQueryStringParameters(uri, params) { for(key in params){ var value = params[key], re = new RegExp("([?&])" + key + "=.*?(&|$)", "i"), separator = uri.indexOf('?') !== -1 ? "&" : "?"; if (uri.match(re)) { uri = uri.replace(re, '$1' + key + "=" + value + '$2'); } else { uri = uri + separator + key + "=" + value; } } return uri; }
和@业余的function一样
如果jslint给你一个错误,在for循环之后加上这个
if(params.hasOwnProperty(key))
在这个页面上有很多尴尬和不必要的复杂的答案。 尽pipe在RegExp中有一些不必要的毛病,但是业余的这个评分最高。 这是一个更清洁的RegExp和一个清洁replace
调用稍微更优化的解决scheme:
function updateQueryStringParamsNoHash(uri, key, value) { var re = new RegExp("([?&])" + key + "=[^&]*", "i"); return re.test(uri) ? uri.replace(re, '$1' + key + "=" + value) : uri + separator + key + "=" + value ; }
作为一个额外的好处,如果uri
不是一个string,你不会因为尝试调用match
或replace
某些可能不会实现这些方法的错误而得到错误。
如果你想处理一个散列的情况(你已经检查了格式正确的HTML),你可以利用现有的函数,而不是写一个包含相同逻辑的新函数:
function updateQueryStringParams(url, key, value) { var splitURL = url.split('#'); var hash = splitURL[1]; var uri = updateQueryStringParamsNoHash(splitURL[0]); return hash == null ? uri : uri + '#' + hash; }
或者你可以对@ Adam做出一些微妙的改变:
function updateQueryStringParameter(uri, key, value) { var re = new RegExp("([?&])" + key + "=[^&#]*", "i"); if (re.test(uri)) { return uri.replace(re, '$1' + key + "=" + value); } else { var matchData = uri.match(/^([^#]*)(#.*)?$/); var separator = /\?/.test(uri) ? "&" : "?"; return matchData[0] + separator + key + "=" + value + (matchData[1] || ''); } }
这应该是有目的的:
function updateQueryString(url, key, value) { var arr = url.split("#"); var url = arr[0]; var fragmentId = arr[1]; var updatedQS = ""; if (url.indexOf("?") == -1) { updatedQS = encodeURIComponent(key) + "=" + encodeURIComponent(value); } else { updatedQS = addOrModifyQS(url.substring(url.indexOf("?") + 1), key, value); } url = url.substring(0, url.indexOf("?")) + "?" + updatedQS; if (typeof fragmentId !== 'undefined') { url = url + "#" + fragmentId; } return url; } function addOrModifyQS(queryStrings, key, value) { var oldQueryStrings = queryStrings.split("&"); var newQueryStrings = new Array(); var isNewKey = true; for (var i in oldQueryStrings) { var currItem = oldQueryStrings[i]; var searchKey = key + "="; if (currItem.indexOf(searchKey) != -1) { currItem = encodeURIComponent(key) + "=" + encodeURIComponent(value); isNewKey = false; } newQueryStrings.push(currItem); } if (isNewKey) { newQueryStrings.push(encodeURIComponent(key) + "=" + encodeURIComponent(value)); } return newQueryStrings.join("&"); }