Cum pot șterge un parametru dintr-un șir de interogare în JavaScript?


Există o modalitate mai bună de a șterge un parametru dintr-un șir de interogare într-un URL în JavaScript standard decât utilizând o expresie regulată?

Iată ce am realizat până acum și pare să funcționeze în testele mele, dar nu îmi place să reinventez analiza stringului de interogare!

function RemoveParameterFromUrl( url, parameter ) {

    if( typeof parameter == "undefined" || parameter == null || parameter == "" ) throw new Error( "parameter is required" );

    url = url.replace( new RegExp( "\\b" + parameter + "=[^&;]+[&;]?", "gi" ), "" ); "$1" );

    // remove any leftover crud
    url = url.replace( /[&;]$/, "" );

    return url;
}

Răspuns #1

"[&;]?" + parameter + "=[^&;]+"

Pare periculos deoarece parametrul ‘bar’ s-ar potrivi:

?a=b&foobar=c

De asemenea, acesta ar eșua dacă parameter conținea orice caracter care este special în RegExp, cum ar fi ‘.’. Și nu este un regex global, așa că ar elimina doar o singură instanță a parametrului.

Nu aș folosi un RegExp simplu pentru asta, aș analiza parametrii și aș pierde pe cei pe care nu-i dorești.

function removeURLParameter(url, parameter) {
    //prefer to use l.search if you have a location/link object
    var urlparts = url.split('?');   
    if (urlparts.length >= 2) {

        var prefix = encodeURIComponent(parameter) + '=';
        var pars = urlparts[1].split(/[&;]/g);

        //reverse iteration as may be destructive
        for (var i = pars.length; i-- > 0;) {    
            //idiom for string.startsWith
            if (pars[i].lastIndexOf(prefix, 0) !== -1) {  
                pars.splice(i, 1);
            }
        }

        return urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : '');
    }
    return url;
}

Răspunsul #2

Browserele moderne oferă interfața URLSearchParams pentru a lucra cu parametrii de căutare. Aceasta are metoda delete care elimină parametrul după nume.

if (typeof URLSearchParams !== 'undefined') {
  const params = new URLSearchParams('param1=1&param2=2&param3=3')
  
  console.log(params.toString())
  
  params.delete('param2')
  
  console.log(params.toString())

} else {
  console.log(`Your browser ${navigator.appVersion} does not support URLSearchParams`)
}

Răspunsul #3

Poți schimba URL-ul cu:

window.history.pushState({}, document.title, window.location.pathname);

în acest fel, poți suprascrie URL-ul fără parametrul de căutare, îl folosesc pentru a curăța URL-ul după ce iau parametrii GET.

Răspunsul #4

Dacă este o instanță de URL, folosește funcția delete a searchParams

let url = new URL(location.href);
url.searchParams.delete('page');

Răspunsul #5

Nu văd probleme majore cu o soluție regex. Dar, nu uitați să păstrați identificatorul de fragment (textul după #).

Iată soluția mea:

function RemoveParameterFromUrl(url, parameter) {
  return url
    .replace(new RegExp('[?&]' + parameter + '=[^&#]*(#.*)?$'), '$1')
    .replace(new RegExp('([?&])' + parameter + '=[^&]*&'), '$1');
}

Și, referindu-ne la punctul lui bobince, da - ar trebui să scapi caracterele . din numele parametrilor.

Răspuns #6

Copiat din răspunsul lui bobince, dar modificat să suporte semne de întrebare în șirul de interogare, de exemplu

http://www.google.com/search?q=test???+something&aq=f

Este valid să existe mai mult de un semn de întrebare într-un URL?

function removeUrlParameter(url, parameter) {
  var urlParts = url.split('?');

  if (urlParts.length >= 2) {
    // Get first part, and remove from array
    var urlBase = urlParts.shift();

    // Join it back up
    var queryString = urlParts.join('?');

    var prefix = encodeURIComponent(parameter) + '=';
    var parts = queryString.split(/[&;]/g);

    // Reverse iteration as may be destructive
    for (var i = parts.length; i-- > 0; ) {
      // Idiom for string.startsWith
      if (parts[i].lastIndexOf(prefix, 0) !== -1) {
        parts.splice(i, 1);
      }
    }

    url = urlBase + '?' + parts.join('&');
  }

  return url;
}

Răspunsul #7

Iată o soluție care:

  1. folosește URLSearchParams (fără expresii regulate greu de înțeles)
  2. actualizează URL-ul în bara de căutare fără reîncărcare
  3. păstrează toate celelalte părți ale URL-ului (de exemplu hash-ul)
  4. elimină ? inutil din șirul de interogare dacă ultimul parametru a fost eliminat
function removeParam(paramName) {
    let searchParams = new URLSearchParams(window.location.search);
    searchParams.delete(paramName);
    if (history.replaceState) {
        let searchString = searchParams.toString().length > 0 ? '?' + searchParams.toString() : '';
        let newUrl = window.location.protocol + "//" + window.location.host + window.location.pathname +  searchString + window.location.hash;
        history.replaceState(null, '', newUrl);
    }
}

Notă: așa cum s-a menționat în alte răspunsuri, URLSearchParams nu este acceptat în IE, așa că folosiți un polyfill.

Răspunsul #8

Iată ce folosesc:

if (location.href.includes('?')) { 
    history.pushState({}, null, location.href.split('?')[0]); 
}

URL original: http://www.example.com/test/hello?id=123&foo=bar
URL destinație: http://www.example.com/test/hello

Acum acest răspuns pare chiar mai bun! (totuși nu a fost testat complet)

Răspunsul #9

Aceasta este o versiune curată eliminați parametrul de interogare folosind clasa URL pentru browserele de astăzi:

function removeUrlParameter(url, paramKey)
{
  var r = new URL(url);
  r.searchParams.delete(paramKey);
  return r.href;
}

URLSearchParams nu este acceptat pe browserele vechi

https://caniuse.com/#feat=urlsearchparams

IE, Edge (sub versiunea 17) și Safari (sub versiunea 10.3) nu suportă URLSearchParams în cadrul clasei URL.

Polyfill-uri

Polyfill doar pentru URLSearchParams

https://github.com/WebReflection/url-search-params

Complete polyfill pentru URL și URLSearchParams pentru a se potrivi cu ultimele specificații WHATWG

https://github.com/lifaon74/url-polyfill

Răspuns #10

Oricine este interesat de o soluție regex, am creat această funcție pentru a adăuga/elimina/actualiza un parametru din șirul de interogare. Nepreferirea unei valori va elimina parametrul, iar preferirea uneia va adăuga/actualiza parametrul. Dacă nu este furnizat niciun URL, acesta va fi preluat din window.location. Această soluție ia în considerare și ancora URL-ului.

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

ACTUALIZARE

A existat o eroare la eliminarea primului parametru din șirul de interogare, am refăcut expresia regulată și testul pentru a include o corecție.

ACTUALIZARE 2

@schellmax actualizare pentru a remedia situația în care simbolul hashtag se pierde atunci când se elimină o variabilă din querystring direct înainte de un hashtag