Как добавить или обновить параметр строки запроса?
С javascript, как я могу добавить параметр строки запроса к URL-адресу, если он отсутствует, или если он присутствует, обновите текущее значение? Я использую jquery для разработки моей клиентской части.
Я написал следующую функцию, которая выполняет то, что я хочу достичь:
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; } }
Я расширил решение и объединил его с другим, который я нашел, чтобы заменить / обновить / удалить параметры запроса на основе ввода пользователей и принять во внимание привязку URL-адресов.
Не указывая значения, вы удалите параметр, и при поставке он добавит / обновит параметр. Если URL не указан, он будет схвачен из windows.
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; } }
Обновить
При удалении первого параметра в querystring произошла ошибка, я переработал регулярное выражение и проверил, чтобы включить исправление.
Второе обновление
Как было предложено @ JarónBarends – проверка значения Tweak для проверки на неопределенный и null, чтобы разрешить установку значений 0
Третье обновление
Была ошибка, при которой удаление переменной querystring непосредственно до того, как hashтег потеряет символ hashтега, который был исправлен
Четвертое обновление
Спасибо @rooby за указание оптимизации регулярных выражений в первом объекте RegExp. Задайте начальное регулярное выражение ([? &]) Из-за проблемы с использованием (\? | &), Найденного @YonatanKarni
Пятое обновление
Удаление объявления hash var в if / else
Утилита 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
независимо от того, существовал он или нет.
Однако указанное выше назначение window.location.search
приведет к загрузке страницы, поэтому, если это нежелательно, используйте 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); }
Теперь вам не нужно писать собственное регулярное выражение или логику для обработки возможного существования строк запроса.
Однако поддержка браузера оставляет желать лучшего, поскольку в настоящее время она является экспериментальной и используется только в последних версиях Chrome, Firefox, Safari, iOS Safari, Android Browser, Android Chrome и Opera. Используйте с полифоном, если вы решите его использовать.
Обновление: поддержка браузера улучшилась с момента моего первоначального ответа.
Основываясь на ответе @ amateur (и теперь включив исправление из комментария @j_walker_dev), но с учетом комментария о hash-тегах в 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; } }
Отредактировано для исправления [?|&]
В регулярном выражении, которое должно быть, конечно, [?&]
Как указано в комментариях
Изменить: Альтернативная версия для поддержки удаления 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; } } }
Смотрите его в действии на https://jsfiddle.net/bp3tmuxh/1/
Вот моя библиотека: https://github.com/Mikhus/jsurl
var u = new Url; u.query.param='value'; // adds or replaces the param alert(u)
window.location.search – чтение / запись.
Однако – изменение строки запроса приведет к перенаправлению страницы, на которой вы находитесь, и вызвать обновление с сервера.
Если то, что вы пытаетесь сделать, это поддерживать состояние на стороне клиента (и, возможно, сделать его доступным для закладок), вы захотите изменить хеш URL вместо строки запроса, который удерживает вас на одной странице (window.location. hash читается / записывается). Вот как это делают веб-сайты, такие как twitter.com.
Вам также понадобится, чтобы кнопка «Назад» работала, вам нужно связать события javascript с событием изменения hashа, хорошим плагином для этого является http://benalman.com/projects/jquery-hashchange-plugin/
Вот мой подход: функция location.params()
(показана ниже) может использоваться как геттер или сеттер. Примеры:
Учитывая 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()
, которая может быть назначена объекту 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- query-object
window.location.search = jQuery.query.set (“param”, 5);
Это мое предпочтение, и оно охватывает случаи, о которых я могу думать. Может ли кто-нибудь подумать о том, как уменьшить его до одной замены?
function setParam(uri, key, val) { return uri .replace(RegExp("([?&]"+key+"(?=[=]|$)[^#&]*|(?=#|$))"), "&"+key+"="+encodeURIComponent(val)) .replace(/^([^?&]+)&/, "$1?"); }
Я знаю, что это довольно старый, но я хочу запустить свою рабочую версию здесь.
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())); } }); });
Я понимаю, что этот вопрос старый, и ему ответили на смерть, но вот мой удар. Я пытаюсь изобрести колесо здесь, потому что я использовал принятый в настоящее время ответ, а неправильное обращение с fragmentами 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 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; }
Мой прием отсюда (совместим с «use strict», на самом деле не использует 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, я придумал следующее решение, которое позволяет при необходимости отключить hash-тег:
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
Вот более короткая версия, которая заботится о
- запрос с заданным параметром или без него
- запрос с несколькими значениями параметров
- запрос, содержащий hash
Код:
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); }
Описание regex можно найти здесь .
ПРИМЕЧАНИЕ . Это решение основано на @amateur ответе, но со многими улучшениями.
Другой подход без использования регулярных выражений . Поддерживает «hash-анкеры» в конце URL-адреса, а также несколько символов вопросительного знака (?). Должно быть немного быстрее, чем подход с регулярным выражением.
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 }
Чтобы привести пример кода для модификации window.location.search
предложенный Gal и tradyblix:
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-скрипт, чтобы найти конкретную строку запроса и заменить ее значение *
('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; } }) });
Да, у меня была проблема, когда моя ошибка повторялась и дублировалась, но это было связано с моей собственной медлительностью. поэтому я немного поиграл и обработал jsquery jsquery (на самом деле шипение) и C # magick.
Поэтому я просто понял, что после того, как сервер выполнил с переданными значениями, значения больше не имеют значения, повторного использования нет, если клиент хотел сделать то же самое, очевидно, что это всегда будет новый запрос, даже если его передаются те же самые параметры. И это все клиенты, поэтому некоторые кеширование / cookies и т. Д. Могут быть classными в этом отношении.
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:
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. } } }
Хорошо критика приветствуется (это была ночная смесь, поэтому не стесняйтесь учитывать корректировки). Если это вообще помогло, сделайте это, Happy Coding.
Никаких дубликатов, каждый запрос не уникален, как вы его модифицировали, и из-за того, как это структурировано, легко добавить динамические запросы от w.
Вот альтернативный метод, использующий встроенные свойства элемента привязки HTML:
- Обрабатывает многозначные параметры.
- Отсутствие риска изменения fragmentа # или ничего, кроме самой строки запроса.
- Может быть, немного легче читать? Но это длиннее.
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; }
такая же функция, как @ amateur’s
если jslint дает вам ошибку, добавьте это после цикла for
if(params.hasOwnProperty(key))
На этой странице много неудобных и излишне сложных ответов. Самый высокий рейтинг, любительский, неплохой, хотя в RegExp есть немного ненужного пуха. Вот несколько более оптимальное решение с чистым RegExp и более чистым replace
вызова:
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
не является строкой, вы не получите ошибок для того, чтобы пытаться вызвать match
или replace
на то, что может не реализовать эти методы.
И если вы хотите обработать случай hashа (и вы уже сделали проверку на правильно отформатированный 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; }
Или вы можете внести некоторые незначительные изменения в отличный ответ от Адама:
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("&"); }