Как я могу добавить или обновить параметр строки запроса? - PullRequest
334 голосов
/ 14 мая 2011

С помощью javascript, как я могу добавить параметр строки запроса в URL, если он отсутствует, или, если он присутствует, обновить текущее значение? Я использую jquery для разработки на стороне клиента.

Ответы [ 24 ]

447 голосов
/ 16 мая 2011

Я написал следующую функцию, которая выполняет то, что я хочу достичь:

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;
  }
}
180 голосов
/ 25 июля 2012

Я расширил решение и скомбинировал его с другим, которое я нашел для замены / обновления / удаления параметров строки запроса, основываясь на вводе пользователя и принимая во внимание привязку 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;
        }
    }
}

Обновление

При удалении первого параметра в строке запроса произошла ошибка, я переработал регулярное выражение и проверил, чтобы включить исправление.

Второе обновление

В соответствии с предложением @ JarónBarends - проверка значения твика для проверки неопределенности и нулевого значения, позволяющего установить 0 значений

Третье обновление

Ошибка при удалении переменной строки запроса непосредственно перед тем, как хэштег потерял символ хештега, который был исправлен

Четвертое обновление

Спасибо @rooby за указание на оптимизацию регулярных выражений в первом объекте RegExp. Установите начальное регулярное выражение в ([? &]) Из-за проблемы с использованием (\? | &), Обнаруженной @ YonatanKarni

Пятое обновление

Удаление объявления хеш-переменной в операторе if / else

70 голосов
/ 09 января 2017

Утилита 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 вызовет загрузку страницы, поэтому, если это нежелательно, используйте 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);
}

Теперь вам не нужно писать собственное регулярное выражение или логику для обработки возможного существования строк запроса.

Однако поддержка браузера оставляет желать лучшего, поскольку в настоящее время он экспериментальный и используется только в последних версиях Chrome, Firefox, Safari, iOS Safari, Android Browser, Android Chrome и Opera. Используйте полифилл , если вы решите его использовать.

Обновление: Улучшена поддержка браузера с момента моего первоначального ответа.

43 голосов
/ 22 февраля 2013

На основании ответа @ 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;
  }
}

Отредактировано, чтобы исправить [?|&] в регулярном выражении, которое, конечно, должно быть [?&], как указано в комментариях

Редактировать: Альтернативная версия, которая также поддерживает удаление параметров 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/

20 голосов
/ 19 апреля 2013

Вот моя библиотека для этого: https://github.com/Mikhus/jsurl

var u = new Url;
u.query.param='value'; // adds or replaces the param
alert(u)
10 голосов
/ 08 мая 2014

Я понимаю, что этот вопрос старый и на него ответили до смерти, но вот мой удар по нему. Я пытаюсь изобрести колесо здесь, потому что я использовал принятый в настоящее время ответ, а недавно неправильно обработанные фрагменты 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;
}
10 голосов
/ 14 мая 2011

window.location.search для чтения / записи.

Однако - изменение строки запроса перенаправит страницу, на которой вы находитесь, и приведет к обновлению с сервера.

Если вы пытаетесь сохранить состояние на стороне клиента (и, возможно, сделать его способным делать закладки), вам нужно изменить хэш URL-адреса вместо строки запроса, которая удерживает вас на той же странице (окно .location.hash - чтение / запись). Вот как это делают такие сайты, как twitter.com.

Вы также захотите, чтобы кнопка «Назад» работала, вам нужно будет привязать события javascript к событию изменения хеша, хороший плагин для этого - http://benalman.com/projects/jquery-hashchange-plugin/

9 голосов
/ 25 января 2015

Вот мой подход: функцию location.params() (показанную ниже) можно использовать как метод получения или установки. Примеры:

Учитывая 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('&');
};
9 голосов
/ 14 мая 2011

Если он не установлен или вы хотите обновить его новым значением, вы можете использовать:

window.location.search = 'param=value'; // or param=new_value

Кстати, в простом Javascript.

РЕДАКТИРОВАТЬ

Вы можете попробовать использовать jquery объект запроса плагин

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

6 голосов
/ 05 августа 2016

Это мое предпочтение, и оно охватывает случаи, о которых я могу подумать. Кто-нибудь может придумать способ уменьшить его до одной замены?

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