javascript - Bir sorgu dizesi parametresini nasıl ekleyebilir veya güncelleyebilirim?


Javascript ile, eğer yoksa URL'ye bir sorgu dizesi parametresi nasıl ekleyebilirim veya varsa mevcut değeri nasıl güncelleyebilirim? İstemci tarafı geliştirme için jquery kullanıyorum.

Cevap #1

İstediğimi başaran aşağıdaki fonksiyonu yazdım:

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

Cevap #2

Güncelleme (2020): URLSearchParams artık tüm modern tarayıcılar tarafından desteklenmektedir.

URLSearchParams aracı, window.location.search ile birlikte bu konuda kullanışlı olabilir. Örneğin:

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

Artık foo, önceden var olup olmadığına bakılmaksızın bar olarak ayarlandı.

Ancak, yukarıdaki window.location.search ataması bir sayfa yüklenmesine neden olacaktır, bu yüzden bu istenmiyorsa History API'sini şu şekilde kullanın:

if ('URLSearchParams' in window) {
  const url = new URL(window.location)
  url.searchParams.set("foo", "bar")
  history.pushState(null, '', url);
}

Artık sorgu dizelerinin olası varlığını ele almak için kendi regex'inizi veya mantığınızı yazmanıza gerek yok.

Cevap #3

Çözümü genişlettim ve kullanıcıların girdilerine göre sorgu dizesi parametrelerini değiştirmek/güncellemek/kaldırmak için bulduğum başka bir çözümle birleştirdim ve URL'nin anchor kısmını da dikkate aldım.

Bir değer verilmemesi parametreyi kaldırır, bir değer verilmesi parametreyi ekler/günceller. Hiçbir URL verilmezse, window.location'dan alınacaktır.

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

Güncelleme

Sorgu dizgesindeki ilk parametreyi kaldırırken bir hata vardı, düzeltmeyi eklemek için regex'i ve testi yeniden düzenledim.

İkinci Güncelleme

@JarónBarends tarafından önerildiği gibi - 0 değerin ayarlanmasına izin vermek için değer kontrolünü tanımsız ve null ile karşılaştıracak şekilde ayarlayın

Üçüncü Güncelleme

Hashtag öncesinde bir sorgu dizesi değişkenini doğrudan kaldırmanın hashtag sembolünü kaybettiren bir hata vardı ve bu düzeltildi

Dördüncü Güncelleme

İlk RegExp nesnesindeki bir regex optimizasyonunu işaret ettiği için @rooby'ya teşekkürler. @YonatanKarni tarafından bulunan (\?|&) kullanımındaki sorun nedeniyle başlangıç regex'ini ([?&]) olarak ayarladık.

Beşinci Güncelleme

if/else ifadesinde hash değişkenini tanımlamayı kaldırma

Cevap #4

Bunu çok basit bir şekilde yapmak için tarayıcının yerleşik URL API'sini kullanabilirsiniz; burada key ve value sırayla parametre adınız ve parametre değerinizdir.

const url = new URL(location.href);
url.searchParams.set(key, value);

Bu, URL hakkındaki her şeyi koruyacak ve yalnızca bir sorgu parametresini değiştirecek veya ekleyecektir.

Daha sonra url nesnesi ile istediğinizi yapabilirsiniz. Örnekler:

// Log the URL string.
console.log(url.href);

// Go to the URL.
location.assign(url);

// Go to the URL, but overwrite this history entry.
location.replace(url);

// Same as `location.assign` without reloading.
history.pushState(null, '', url);

// Same as `location.replace` without reloading.
history.replaceState(null, '', url);

Cevap #5

@amateur'un cevabına dayanarak (ve şimdi @j_walker_dev yorumundaki düzeltmeyi de ekleyerek), ancak url'deki hash etiketleri hakkındaki yorumu dikkate alarak şu şekilde kullanıyorum:

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

Yorumlarda belirtildiği gibi elbette [?&] olması gereken regex'teki [?|&] düzeltmek için düzenlendi

Düzenleme: URL parametrelerini kaldırmayı destekleyen alternatif sürüm. Kaldırmayı belirtmek için value === undefined kullandım. İstenirse value === false veya ayrı bir giriş parametresi de kullanılabilir.

function updateQueryStringParameter(uri, key, value) {
  var re = new RegExp("([?&])" + key + "=.*?(&|#|$)", "i");
  if( value === undefined ) {
    if (uri.match(re)) {
    return uri.replace(re, '$1$2').replace(/[?&]$/, '').replaceAll(/([?&])&+/g, '$1').replace(/[?&]#/, '#');
  } 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/cdt16wex/ adresinde kullanımını görün

Cevap #6

Modern JavaScript, Node.js ve tarayıcı desteği sayesinde, üçüncü taraf kütüphane girdabından (jQuery, query-string vb.) çıkabilir ve kendimizi DRY yapabiliriz.

İşte verilen URL'nin sorgu parametrelerini ekleyen veya güncelleyen bir fonksiyon için javascript(node.js) ve typescript sürümü:

Javascript

const getUriWithParam = (baseUrl, params) => {
  const Url = new URL(baseUrl);
  const urlParams = new URLSearchParams(Url.search);
  for (const key in params) {
    if (params[key] !== undefined) {
      urlParams.set(key, params[key]);
    }
  }
  Url.search = urlParams.toString();
  return Url.toString();
};

console.info('expected: https://example.com/?foo=bar');
console.log(getUriWithParam("https://example.com", {foo: "bar"}));

console.info('expected: https://example.com/slug?foo=bar#hash');
console.log(getUriWithParam("https://example.com/slug#hash", {foo: "bar"}));

console.info('expected: https://example.com/?bar=baz&foo=bar');
console.log(getUriWithParam("https://example.com?bar=baz", {foo: "bar"}));

console.info('expected: https://example.com/?foo=baz&bar=baz');
console.log(getUriWithParam("https://example.com?foo=bar&bar=baz", {foo: "baz"}));

Typescript

const getUriWithParam = (
  baseUrl: string,
  params: Record<string, any>
): string => {
  const Url = new URL(baseUrl);
  const urlParams: URLSearchParams = new URLSearchParams(Url.search);
  for (const key in params) {
    if (params[key] !== undefined) {
      urlParams.set(key, params[key]);
    }
  }
  Url.search = urlParams.toString();
  return Url.toString();
};

React Native için

URL React Native'de uygulanmamıştır. Bu yüzden önceden react-native-url-polyfill kurmanız gerekmektedir.

Nesne parametreleri için

Bu cevapta ikinci çözüme bakın

Cevap #7

Bunu yapmak için kütüphanem burada: https://github.com/Mikhus/jsurl

var u = new Url;
u.query.param='value'; // adds or replaces the param
alert(u)

Cevap #8

Eğer ayarlanmadıysa veya yeni bir değerle güncellemek istiyorsanız şunu kullanabilirsiniz:

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

Bu arada bu basit Javascript ile yapılmıştır.

DÜZENLE

jquery query-object eklentisini kullanmayı deneyebilirsiniz

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

Cevap #9

Bu sorunun eski olduğunu ve defalarca yanıtlandığını farkındayım, ama işte benim denemem. Burada tekerleği yeniden icat etmeye çalışıyorum çünkü şu anda kabul edilen cevabı kullanıyordum ve URL parçalarının yanlış yönetilmesi yakın zamanda bir projede bana sorun çıkardı.

Fonksiyon aşağıdadır. Oldukça uzun, ama mümkün olduğunca dayanıklı olacak şekilde yapıldı. Kısaltmak/geliştirmek için önerilere bayılırım. Bunun için (veya benzeri diğer fonksiyonlar için) küçük bir jsFiddle test seti hazırladım. Bir fonksiyon oradaki her testi geçebiliyorsa, muhtemelen kullanılmaya hazır olduğunu söyleyebilirim.

Güncelleme: URL'leri çözümlemek için DOM'u kullanmaya yarayan harika bir fonksiyonla karşılaştım, bu yüzden bu tekniği burada kullandım. Fonksiyonu daha kısa ve daha güvenilir hale getiriyor. O fonksiyonun yazarı takdir edilmeli.

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

Cevap #10

window.location.search okunur/yazılır.

Ancak - sorgu dizgisini değiştirmek, bulunduğunuz sayfayı yönlendirir ve sunucudan yenilenmesine neden olur.

Eğer yapmaya çalıştığınız şey istemci tarafı durumu korumaksa (ve potansiyel olarak yer imlerine eklenebilir hale getirmekse), sorgu dizesi yerine URL hash'ini değiştirmeniz gerekir, bu da sizi aynı sayfada tutar (window.location.hash okunabilir/yazılabilir). Twitter.com gibi web siteleri bunu böyle yapar.

Geri düğmesinin de çalışmasını isteyeceksiniz, bunun için javascript olaylarını hash değişikliği olayına bağlamanız gerekecek, bunun için iyi bir eklenti http://benalman.com/projects/jquery-hashchange-plugin/

İlgili makaleler