Jak mogę dodać lub zaktualizować parametr ciągu zapytania?

364

W javascript, jak mogę dodać parametr ciągu zapytania do adresu URL, jeśli nie jest obecny, lub jeśli jest obecny, zaktualizować bieżącą wartość? Używam jquery do programowania po stronie mojego klienta.

amator
źródło
1
Wygląda na to, że napisałem w JavaScript JavaScript funkcję „parseQueryString” około 100 razy. To nie jest trudne. Kluczowe punkty, String#splitprzyjmuje drugi parametr dla maksymalnych podziałów. mapPomocne będą także jQuery's .
jpsimons
Ten post zawiera również wiele rozwiązań stackoverflow.com/questions/1090948/...
Dilip Rajkumar
1
Niektóre osoby uważają to pytanie za „jak zmienić adres URL w pasku adresu”, a inne „jak zmienić dowolną zmienną adresu URL”
PandaWood
możliwy duplikat stackoverflow.com/questions/486896/…
Użytkownik

Odpowiedzi:

468

Napisałem następującą funkcję, która osiąga to, co chcę osiągnąć:

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;
  }
}
amator
źródło
36
Ta odpowiedź nie działa, gdy w identyfikatorze URI występuje skrót - ciągi zapytania muszą zostać umieszczone przed skrótem, w przeciwnym razie nie zostaną przesłane na serwer. jsfiddle.net/4yXzR
Greg
20
[?|&]powinno być[?&]
soju,
8
Ogranicz zakres zmiennych separatora do funkcji lokalnej, dodając vartuż przed deklaracją separatora.
Andrea Salicetti,
3
Myślę, że powinieneś dodać value = encodeURIComponent(value);w pierwszym wierszu, w przeciwnym razie podziały wiersza nie zostaną poprawnie zmienione.
Felix
18
Zajmie się
Niyaz
189

Rozszerzyłem to rozwiązanie i połączyłem je z innym, które znalazłem, aby zastąpić / zaktualizować / usunąć parametry zapytania w oparciu o dane wprowadzone przez użytkowników i biorąc pod uwagę zakotwiczenie adresów URL.

Brak podania wartości spowoduje usunięcie parametru, podanie jednego spowoduje dodanie / aktualizację parametru. Jeśli nie zostanie podany żaden adres URL, zostanie on pobrany z 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;
        }
    }
}

Aktualizacja

Wystąpił błąd podczas usuwania pierwszego parametru z kwerendy, przerobiłem wyrażenie regularne i przetestowałem, aby uwzględnić poprawkę.

Druga aktualizacja

Jak sugeruje @ JarónBarends - Popraw wartość, aby sprawdzić przed niezdefiniowanym i zerowym, aby umożliwić ustawienie 0 wartości

Trzecia aktualizacja

Wystąpił błąd polegający na tym, że usunięcie zmiennej zapytania bezpośrednio przed hashtagiem utraciło naprawiony symbol hashtagu

Czwarta aktualizacja

Dzięki @rooby za wskazanie optymalizacji wyrażeń regularnych w pierwszym obiekcie RegExp. Ustaw początkowe wyrażenie regularne na ([? &]) Z powodu problemu z użyciem (\? | &) Znalezionego przez @YonatanKarni

Piąta aktualizacja

Usunięcie deklarującej zmiennej hash w instrukcji if / else

ellemayo
źródło
5
Już samo sprawdzenie „prawdziwości” valuespowoduje usunięcie zmiennych z kwerendy, gdy ustawisz ich wartość na 0. Więc zamiast tego if (value) {}powinieneś użyćif (typeOf value !== 'undefined' && value !== null) {}
Jarón Barends 16.04.13
1
W RegExp ([? | &]) Powinien być naprawdę ([? &])
rooby
Zabawne, jak to przeniesiono z oryginalnego rozwiązania - można również użyć (\? | &)
ellemayo
1
uzyskiwanie „niepoprawnego wyjątku regularnego / nieprawidłowej grupy” wyjątku dotyczącego tworzenia wyrażenia regularnego w chrome Wersja 31.0.1650.63, rozwiązane przez zwrócenie początku na „([? &])”
Yonatan Karni
1
Nie ma to znaczenia, z wyjątkiem tego, że jestem OCD, ale zmienna hashjest deklarowana dwukrotnie;)
wlingke
117

Narzędzie URLSearchParams może być do tego przydatne w połączeniu z window.location.search. Na przykład:

if ('URLSearchParams' in window) {
    var searchParams = new URLSearchParams(window.location.search);
    searchParams.set("foo", "bar");
    window.location.search = searchParams.toString();
}

Teraz fooustawiono nabar niezależnie od tego, czy już istnieje.

Jednak powyższe przypisanie window.location.searchspowoduje załadowanie strony, więc jeśli nie jest to pożądane, użyj interfejsu API historii w następujący sposób:

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);
}

Teraz nie musisz pisać własnego wyrażenia regularnego ani logiki, aby obsłużyć możliwe istnienie ciągów zapytań.

Jednak obsługa przeglądarki jest słaba, ponieważ jest obecnie eksperymentalna i jest używana tylko w najnowszych wersjach Chrome, Firefox, Safari, iOS Safari, Android Browser, Android Chrome i Opera. Użyj z polifillem, jeśli zdecydujesz się go użyć.

Aktualizacja: Obsługa przeglądarki poprawiła się od czasu mojej pierwotnej odpowiedzi.

Anthony Manning-Franklin
źródło
wypełnianie Unable to set property '__URLSearchParams__:0.8503766759030615' of undefined or null reference polly , nie jest dobre, na ie11 pojawia się ten błąd. to nie jest pollyfill, jeśli nie działa jako rezerwowy.
Val
6
Aktualizacja 2019 : Obsługa przeglądarek jest teraz dobra dla większości przeglądarek oprócz IE i niektórych małych przeglądarek mobilnych. Nowa funkcja polifillu ungap z łatwością pokrywa to: github.com/ungap/url-search-params
Flion 30.04.2019
Idealna odpowiedź, jednak nie obsługuje usecase, gdy hashtag jest obecny w adresie URL. Proste dodanie skrótu na końcu newRelativePathQueryrobi lewę:var newRelativePathQuery = window.location.pathname + '?' + searchParams.toString() + window.location.hash;
kudlohlavec
43

Na podstawie odpowiedzi @ amatora (i teraz zawierającej poprawkę z komentarza @j_walker_dev), ale biorąc pod uwagę komentarz dotyczący znaczników skrótu w adresie URL, używam następujących elementów:

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;
  }
}

Edytowane, aby naprawić [?|&]w wyrażeniach regularnych, które oczywiście powinny być takie, [?&]jak wskazano w komentarzach

Edycja: Alternatywna wersja do obsługi usuwania parametrów adresu URL. Użyłem value === undefinedjako sposobu wskazania usunięcia. Można użyć value === falselub nawet osobnego parametru wejściowego zgodnie z potrzebami.

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;
  }
  }  
}

Zobacz to w akcji na https://jsfiddle.net/bp3tmuxh/1/

Adam
źródło
2
Dużo czystsze. FYI dla kątowych użytkowników interfejsu użytkownika routera, którzy mogą mieć „?” również w haszu. Przesunięcie var separatorlinii w prawo nad zwrotem naprawia błąd z „/ app # / cool? Fun = true”. To wybrałoby „&” jako separator, nawet jeśli nie ma jeszcze prawdziwych parametrów ciągu zapytania. Tylko klient.
j_walker_dev
3
Jak wskazano w komentarzach do innych odpowiedzi, [?|&]powinno być po prostu [?&](w przeciwnym razie będzie pasować |).
bonger
1
Tak, "([?|&])"nie jest dobrze. Proszę to naprawić albo jako var re = new RegExp("(?|&)" + key + "=.*?(&|#|$)", "i");lub var re = new RegExp("([?&])" + key + "=.*?(&|#|$)", "i");(miły rozszerzenia w inny sposób!)
YakovL
ok, przepraszam, var re = new RegExp("(?|&)" + key + "=.*?(&|#|$)", "i");nie działa, drugi działa
JakowL
Wygląda na to, że ta wersja nie obsługuje usuwania parametru ciągu zapytania poprzez pominięcie wartości. Czy mam rację?
jkupczak
11

window.location.search jest do odczytu / zapisu.

Jednak - zmodyfikowanie ciągu zapytania spowoduje przekierowanie strony, na której jesteś, i spowoduje odświeżenie z serwera.

Jeśli próbujesz zachować stan po stronie klienta (i potencjalnie sprawić, że będzie można go dodawać do zakładek), będziesz chciał zmodyfikować skrót adresu URL zamiast ciągu zapytania, co utrzyma cię na tej samej stronie (window.location). hash to read / write). W ten sposób robią to strony internetowe takie jak twitter.com.

Będziesz także chciał, aby przycisk Wstecz działał, będziesz musiał powiązać zdarzenia javascript ze zdarzeniem zmiany skrótu, dobrym pluginem do tego jest http://benalman.com/projects/jquery-hashchange-plugin/

Gal
źródło
4
Twitter nie modyfikuje już skrótu! Hash nie żyje, witaj w History API !
Alba Mendez,
jest daleki od śmierci. myślę, że mieszkasz w magicznej krainie snów, w której starsza kompatybilność z przeglądarkami nie ma znaczenia. może tak być w przypadku ciebie, ale z pewnością nie dotyczy to reszty z nas (lub w rzeczywistości większości z nas). być może umieranie jest bardziej odpowiednie ...
AaronHS
1
Rok później wygląda na to, że jedyną półautomatyczną przeglądarką, która jej nie obsługuje, jest IE 9
Douglas.Sesar
11

Jeśli nie jest ustawiony lub chcesz zaktualizować o nową wartość, możesz użyć:

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

Nawiasem mówiąc, jest to proste JavaScript.

EDYTOWAĆ

Możesz spróbować użyć wtyczki obiekt zapytania do obiektu jquery

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

tradyblix
źródło
1
nie zachowa to jednak żadnych innych parametrów ciągu zapytania w adresie URL.
amator
masz rację, przepraszam .. jako aktualizację dodałem kolejną opcję do mojej odpowiedzi :)
tradyblix
To nie działa, ponieważ nie resetuje wartości. „dodaj lub zaktualizuj”
Paolo Falomo
11

Zdaję sobie sprawę, że to pytanie jest stare i zostało udzielone odpowiedzi na śmierć, ale oto moje dźgnięcie. Próbuję tu wymyślić na nowo koło, ponieważ korzystałem z obecnie akceptowanej odpowiedzi, a niewłaściwe obchodzenie się z fragmentami adresów URL ostatnio ugryzło mnie w projekt.

Funkcja znajduje się poniżej. Jest dość długi, ale został stworzony tak, aby był jak najbardziej odporny. Chciałbym sugestie dotyczące skrócenia / poprawy. Przygotowałem dla niego mały pakiet testowy jsFiddle (lub inne podobne funkcje). Jeśli jakaś funkcja może przejść każdy z testów, mówię, że prawdopodobnie dobrze jest przejść.

Aktualizacja: natknąłem się na fajną funkcję do używania DOM do analizowania adresów URL , więc zastosowałem tę technikę tutaj. Dzięki temu funkcja jest krótsza i bardziej niezawodna. Podpowiada autorowi tej funkcji.

/**
 * 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;
}
Dominic P.
źródło
2
Wygląda to naprawdę dobrze, solidne przypadki testowe + przy użyciu DOM jako parsera adresów URL. Znalazłam dwa przypadki choć: example.com/?param=val& => example.com/?param=val&&new=key --double & i example.com/team => example.com/team?new=key spodziewanych: team /? new = key some redirect / team? new = key to / team /, a zapytania zostaną utracone.
Timar Ivo Batis
1
Dzięki za nieudany przypadek testowy. Zaktualizowałem skrzypce. Ten pierwszy jest trudny. Jakieś pomysły, jak to naprawić? Drugi nie powinien być obsługiwany bez problemu i jest już objęty pakietem testowym. Może jednak cię nie rozumiem. Możesz rozwidlić skrzypce testowe, aby pokazać, co widzisz.
Dominic P,
Dodałem kilka przypadków testowych, na które natknąłem się i obejścia. Próbowałem używać DOM w jak największym stopniu. Przede wszystkim potrzebowałem tego, aby działał także dla względnych linków w tej samej domenie. jsfiddle.net/Timar/7sjrhbm3
Ivo Batis
1
@braed Podoba mi się podejście, ponieważ pozostawia ciężkie podnoszenie do przeglądarki. Jak widać z wielu odpowiedzi tutaj, ten problem nie jest tak prosty, jak się wydaje. Istnieje wiele narożnych skrzynek, które rozwiązanie musi obejmować. Większość z nich jest objęta darmową gwarancją, gdy wykorzystasz DOM.
Dominic P
1
@braed na pewno spójrz na pakiet testowy, który podałem w odpowiedzi. Wiele rozwiązań, które nie polegają na DOM, zawodzi, ponieważ nie uwzględniają wszystkich wymienionych przypadków brzegowych. Jeśli chodzi o czytanie, warto zapoznać się z modułem URL dla node.js. Nie jest to bezpośrednio powiązane, ale daje wyobrażenie o złożoności związanej z ciągami adresów URL.
Dominic P
9

Oto moje podejście: location.params() Funkcja (pokazana poniżej) może być używana jako getter lub setter. Przykłady:

Biorąc pod uwagę, że adres URL jest http://example.com/?foo=bar&baz#some-hash,

  1. location.params() zwróci obiekt ze wszystkimi parametrami zapytania: {foo: 'bar', baz: true} .
  2. location.params('foo') wróci 'bar' .
  3. location.params({foo: undefined, hello: 'world', test: true})zmieni adres URL na http://example.com/?baz&hello=world&test#some-hash.

Oto params()funkcja, którą można opcjonalnie przypisać do window.locationobiektu.

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('&');
};
jake
źródło
6

To moja preferencja i obejmuje przypadki, o których mogę myśleć. Czy ktoś może pomyśleć o sposobie zredukowania go do pojedynczego zamiennika?

function setParam(uri, key, val) {
    return uri
        .replace(RegExp("([?&]"+key+"(?=[=&#]|$)[^#&]*|(?=#|$))"), "&"+key+"="+encodeURIComponent(val))
        .replace(/^([^?&]+)&/, "$1?");
}
Adam Leggett
źródło
Również nie udaje się kilka przypadków testowych autorstwa Dominic P. stackoverflow.com/a/23529943/8385841
Timar Ivo Batis
5

Wiem, że to jest dość stare, ale chcę tutaj odpalić swoją działającą wersję .

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>

UWAGA To jest zmodyfikowana wersja @elreimundo

Paolo Falomo
źródło
2

Moje podejście stąd (zgodne z „use strict”; tak naprawdę nie używa 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);
}

Przykładowe użycie:

// 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()));
});
Andrey Tarantsov
źródło
2

Na podstawie odpowiedzi udzielonej przez @ellemayo wymyśliłem następujące rozwiązanie, które w razie potrzeby pozwala na wyłączenie tagu 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;
}

Nazwij to tak:

updateQueryString('foo', 'bar', {
    url: 'http://my.example.com#hash',
    hash: false
});

Prowadzi do:

http://my.example.com?foo=bar
RuubW
źródło
Sprzeczność stylistyczna: typeof value !== 'undefined' && value !== nulljest bardziej wyraźna, ale value != nulloznacza to samo i jest bardziej zwięzła.
eppsilon
2

Oto krótsza wersja, która się tym zajmuje

  • zapytanie z danym parametrem lub bez niego
  • zapytanie z wieloma wartościami parametrów
  • zapytanie zawierające skrót

Kod:

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 opis można znaleźć tutaj .

UWAGA : To rozwiązanie jest oparte na odpowiedzi @amateur, ale z wieloma ulepszeniami.

MaxZoom
źródło
2

Kod, który dołącza listę parametrów do istniejącego adresu URL za pomocą ES6 i jQuery:

class UrlBuilder {
    static appendParametersToUrl(baseUrl, listOfParams) {

        if (jQuery.isEmptyObject(listOfParams)) {
            return baseUrl;
        }

        const newParams = jQuery.param(listOfParams);

        let partsWithHash = baseUrl.split('#');
        let partsWithParams = partsWithHash[0].split('?');

        let previousParams = '?' + ((partsWithParams.length === 2) ? partsWithParams[1] + '&' : '');
        let previousHash = (partsWithHash.length === 2) ? '#' + partsWithHash[1] : '';

        return partsWithParams[0] + previousParams + newParams + previousHash;
    }
}

Gdzie jest listOfParams

const listOfParams = {
    'name_1': 'value_1',
    'name_2': 'value_2',
    'name_N': 'value_N',
};

Przykład użycia:

    UrlBuilder.appendParametersToUrl(urlBase, listOfParams);

Szybkie testy:

    url = 'http://hello.world';
    console.log('=> ', UrlParameters.appendParametersToUrl(url, null));
    // Output:  http://hello.world

    url = 'http://hello.world#h1';
    console.log('=> ', UrlParameters.appendParametersToUrl(url, null));
    // Output:  http://hello.world#h1

    url = 'http://hello.world';
    params = {'p1': 'v1', 'p2': 'v2'};
    console.log('=> ', UrlParameters.appendParametersToUrl(url, params));
    // Output: http://hello.world?p1=v1&p2=v2

    url = 'http://hello.world?p0=v0';
    params = {'p1': 'v1', 'p2': 'v2'};
    console.log('=> ', UrlParameters.appendParametersToUrl(url, params));
    // Output: http://hello.world?p0=v0&p1=v1&p2=v2

    url = 'http://hello.world#h1';
    params = {'p1': 'v1', 'p2': 'v2'};
    console.log('=> ', UrlParameters.appendParametersToUrl(url, params));
   // Output: http://hello.world?p1=v1&p2=v2#h1

    url = 'http://hello.world?p0=v0#h1';
    params = {'p1': 'v1', 'p2': 'v2'};
    console.log('=> ', UrlParameters.appendParametersToUrl(url, params));
    // Output: http://hello.world?p0=v0&p1=v1&p2=v2#h1
Samuel Vicent
źródło
1

Inne podejście bez użycia wyrażeń regularnych . Obsługuje kotwice „mieszające” na końcu adresu URL, a także wiele znaków znaku zapytania (?). Powinien być nieco szybszy niż podejście do wyrażeń regularnych.

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
}
cwills
źródło
1

Ta funkcja służy do dodawania, usuwania i modyfikowania parametru ciągu zapytania z adresu URL na podstawie jquery

/**
@param String url
@param object param {key: value} query parameter
*/
function modifyURLQuery(url, param){
    var value = {};

    var query = String(url).split('?');

    if (query[1]) {
        var part = query[1].split('&');

        for (i = 0; i < part.length; i++) {
            var data = part[i].split('=');

            if (data[0] && data[1]) {
                value[data[0]] = data[1];
            }
        }
    }

    value = $.extend(value, param);

    // Remove empty value
    for (i in value){
        if(!value[i]){
            delete value[i];
        }
    }

    // Return url with modified parameter
    if(value){
        return query[0] + '?' + $.param(value);
    } else {
        return query[0];
    }
}

Dodaj nowy i zmodyfikuj istniejący parametr do adresu URL

var new_url = modifyURLQuery("http://google.com?foo=34", {foo: 50, bar: 45});
// Result: http://google.com?foo=50&bar=45

Usuń istniejące

var new_url = modifyURLQuery("http://google.com?foo=50&bar=45", {bar: null});
// Result: http://google.com?foo=50
Jay Padaliya
źródło
1

Korzystając z jQuerytego możemy zrobić jak poniżej

var query_object = $.query_string;
query_object["KEY"] = "VALUE";
var new_url = window.location.pathname + '?'+$.param(query_object)

W zmiennej new_url będziemy mieć nowe parametry zapytania.

Odniesienie: http://api.jquery.com/jquery.param/

anjaneyulubatta505
źródło
0

Aby podać przykład kodu do modyfikacji window.location.searchzgodnie z sugestiami Gal i 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;
Risadinha
źródło
0

Kod skryptu Java, aby znaleźć określony ciąg zapytania i zastąpić jego wartość *

('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;
                }
            })
        });
Mohamed.Abdo
źródło
0

Tak, miałem problem z przepełnieniem i zduplikowaniem mojego zapytania, ale było to spowodowane moją własną powolnością. więc grałem trochę i opracowałem js jquery (właściwie skwierczenie) i magię C #.

Właśnie zdałem sobie sprawę, że po tym, jak serwer wykona przekazane wartości, wartości nie mają już znaczenia, nie ma ponownego użycia, jeśli klient chciał zrobić to samo, to oczywiście zawsze będzie nowe żądanie, nawet jeśli jest to przekazywane są te same parametry. I to wszystko po stronie klienta, więc niektóre buforowanie / pliki cookie itp. Mogą być fajne pod tym względem.

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>

DO#:

    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.
          }
      }
  }

Dobra krytyka jest mile widziana (to była nocna mikstura, więc nie krępuj się zauważyć korekty). Jeśli to w ogóle pomogło, podnieś to, Happy Coding.

Żadnych duplikatów, każde żądanie jest tak unikalne, jak je zmodyfikowałeś, a ze względu na jego strukturę łatwo dodawać kolejne zapytania dynamicznie z poziomu domeny.

LokizFenrir
źródło
0

Oto alternatywna metoda wykorzystująca wbudowane właściwości zakotwiczonego elementu HTML:

  • Obsługuje parametry o wielu wartościach.
  • Brak ryzyka modyfikacji fragmentu # lub czegokolwiek innego niż sam ciąg zapytania.
  • Może być trochę łatwiejszy do odczytania? Ale to jest dłuższe.

    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;
	};

GlennS
źródło
0

jeśli chcesz ustawić wiele parametrów jednocześnie:

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;
}

taka sama funkcja jak @ amatorska

jeśli jslint daje błąd, dodaj to po pętli for

if(params.hasOwnProperty(key))
Rachid O
źródło
Nie obsługuje skrótów ani parametrów, którym nie przypisano wartości ( http://abc.def/?a&b&c).
Adam Leggett,
0

Na tej stronie znajduje się wiele niezręcznych i niepotrzebnie skomplikowanych odpowiedzi. Najwyżej oceniany @ amator jest całkiem niezły, chociaż ma trochę niepotrzebnego puchu w RegExp. Oto nieco bardziej optymalne rozwiązanie z czystszym RegExp i czystszym replacepołączeniem:

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
  ;
}

Jako dodatkowy bonus, jeśli urinie jest ciągiem, nie będziesz otrzymywać błędów podczas próby połączenia matchlubreplace na czymś, co może nie implementować tych metod.

A jeśli chcesz obsłużyć przypadek skrótu (i sprawdziłeś już poprawnie sformatowany HTML), możesz wykorzystać istniejącą funkcję zamiast pisać nową funkcję zawierającą tę samą logikę:

function updateQueryStringParams(url, key, value) {
    var splitURL = url.split('#');
    var hash = splitURL[1];
    var uri = updateQueryStringParamsNoHash(splitURL[0]);
    return hash == null ? uri : uri + '#' + hash;
}

Lub możesz wprowadzić niewielkie zmiany w doskonałej odpowiedzi @ Adama:

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] || '');
  }
}
elreimundo
źródło
2
To brakujący nawias w ostatniej funkcji: var matchData = uri.match (/^([^#]*)(#.*)?$/
Jammer
separatornie jest zdefiniowany w updateQueryStringParamsNoHash. W updateQueryStringParameterwszystko się psuje, jeśli zastępowanemu parametrowi nie jest przypisana wartość (np http://abc.def/?a&b&c.).
Adam Leggett,
0

Powinno to służyć celowi:

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("&");
}   
mmuzahid
źródło