¿Cómo puedo eliminar un parámetro de cadena de consulta en JavaScript?

127

¿Hay una mejor manera de eliminar un parámetro de una cadena de consulta en una cadena URL en JavaScript estándar que no sea mediante el uso de una expresión regular?

Esto es lo que se me ocurrió hasta ahora, que parece funcionar en mis pruebas, ¡pero no me gusta reinventar el análisis de la cadena de consulta!

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;
}
Matthew Lock
fuente

Respuestas:

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

Parece peligroso porque su parámetro 'bar' coincidiría:

?a=b&foobar=c

Además, fallaría si parametercontuviera algún carácter que sea especial en RegExp, como '.'. Y no es una expresión regular global, por lo que solo eliminaría una instancia del parámetro.

No usaría un simple RegExp para esto, analizaría los parámetros y perdería los que no desea.

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;
}
bobince
fuente
Buen punto sobre la barra que coincide con el foobar. ¿He actualizado mi expresión regular original para requerir un? o un [&;] al comienzo. También leer sobre la solución a tener en cuenta es ...
Mateo bloqueo
55
Si quieres deshacerte del "?" cuando no haya parámetros después de la eliminación, agregue una condición if para probar si pars.length == 0, y si es 0, entonces haga "url = urlparts [0]" en lugar de agregar el "?".
johnmcaliley
2
¿Es seguro comparar el fragmento de URL con encodeURIComponent (parámetro)? ¿Qué sucede si la URL codifica el nombre del parámetro de manera diferente? Por ejemplo, 'dos% 20 palabras' versus 'dos ​​+ palabras'. Para lidiar con esto, podría ser mejor decodificar el nombre del parámetro y compararlo como una cadena normal.
Adrian Pronk
9
Mejora leve, de modo que cuando se elimina el parámetro de URL final, el '?' también se elimina: cambia la línea url= urlparts[0]+'?'+pars.join('&');aurl= urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : "");
Cody S
2
Los parámetros de consulta de URL @ ktutnik / @ JonasAxelsson no distinguen entre mayúsculas y minúsculas.
bobince
30

Los navegadores modernos proporcionan una URLSearchParamsinterfaz para trabajar con parámetros de búsqueda. Que tiene un deletemétodo que elimina el parámetro por nombre.

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

Yury Tarabanko
fuente
2
Tenga en cuenta que URLSearchParamsno es compatible con IE, Edge 16 y iOS 10.2 Safari. (ref: caniuse.com/#feat=urlsearchparams )
khiav reoy
3
@khiavreoy Sí. Al igual que las dos primeras palabras en la respuesta, da el mismo enlace :)
Yury Tarabanko
23

Copiado de la respuesta de bobince, pero lo hizo compatible con signos de interrogación en la cadena de consulta, por ejemplo

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

¿Es válido tener más de un signo de interrogación en una 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;
}
LukePH
fuente
2
Creo que la ???sintaxis no es válida y nunca debe aparecer en una URL`.
@torazaburo Eche un vistazo a la pregunta de stackoverflow que publiqué: "¿Es válido tener más de un signo de interrogación en una URL?", la respuesta parece ser sí. También esto fue hace años, así que no puedo recordar los detalles, pero me encontré con problemas cuando esto no se manejó correctamente.
LukePH
No digo que no existan en el mundo real, y uno probablemente querría poder manejarlos, pero en una URL correctamente formada, el signo de interrogación es un "carácter reservado" y cualquier signo de interrogación que no sea el La introducción de los parámetros de consulta debe estar codificada en URL.
1
Es posible que desee reemplazar la última línea return url.endsWith("?") ? url.slice(0,-1) : url;para cubrir el caso en el que el parámetro que se eliminará es el único en la cadena de consulta
Konamiman
@Konamiman Eso cambiaría los datos de los parámetros cuando, por ejemplo, elimine 'aq' de: google.com/search?q=test???&aq=f pero entiendo lo que quiere decir, sería bueno limpiar la URL incluso si el ? No hace ningún daño. ¿La lógica solo necesita asegurarse de que sea la última? es tambien el primero?
LukePH
21

No veo problemas importantes con una solución regex. Pero no olvides preservar el identificador de fragmento (texto después del #).

Aquí está mi solución:

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

Y para el punto de bobince, sí, necesitarías escapar de los .caracteres en los nombres de los parámetros.

Jared
fuente
1
Aquí hay una expresión regular mejorada que funciona cuando el parámetro no tiene valor (es decir, 'ex.com?removeMe') y no reemplazará el parámetro en fragmentos (es decir, 'ex.com?#&dont=removeMe') o rutas (es decir, ' ex.com/&dont=removeMe '):url.replace(new RegExp('^([^#]*\?)(([^#]*)&)?' + parameter + '(\=[^&#]*)?(&|#|$)' ), '$1$3$5').replace(/^([^#]*)((\?)&|\?(#|$))/,'$1$3$4')
Stephen M. Harris
Esto no funcionará Stephen M. Harris. Intente darle a su código una Cadena vacía como parámetro y vea qué sucede ...
David Fischer
15

Puede cambiar la URL con:

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

de esta manera, puede sobrescribir la URL sin el parámetro de búsqueda, lo uso para limpiar la URL después de tomar los parámetros GET.

Santi Nunez
fuente
13

Cualquier persona interesada en una solución regex he creado esta función para agregar / eliminar / actualizar un parámetro de cadena de consulta. Si no se proporciona un valor, se eliminará el parámetro; si se proporciona uno, se agregará / actualizará el parámetro. Si no se proporciona ninguna URL, se tomará de window.location. Esta solución también tiene en cuenta el ancla de la url.

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

ACTUALIZAR

Hubo un error al eliminar el primer parámetro en la cadena de consulta, he reelaborado la expresión regular y la prueba para incluir una solución.

ACTUALIZACIÓN 2

Actualización de @schellmax para corregir la situación en la que se pierde el símbolo de hashtag al eliminar una variable de cadena de consulta directamente antes de un hashtag

revs ellemayo
fuente
1
Esto no funciona si tiene dos cadenas de consulta y elimina la primera. La url pasada se invalida porque el? se elimina cuando se debe preservar.
Blake Niemyjski
1
@BlakeNiemyjski gracias por encontrar ese error, he actualizado el script para incluir una solución para el primer parámetro
ellemayo
1
eliminará accidentalmente el hash aquí:UpdateQueryString('a', null, 'http://www.test.com?a=b#c');
schellmax
Función genial, gracias. FYI: mientras se usa esto con una clave de matriz ignorada en cada bucle () `, es posible que deba definir una reducción cada vez mayor urlpara cada iteración de reemplazo. Pero, eso significa que debe ingresar a valueen los argumentos, lo que dejará la cadena de consulta a medio quitar. Para contrarrestar esto, use undefinedo nullpara valueargumentos como:url_from_last_iteration = UpdateQueryString(current_ignore_key, undefined/null, url_from_last_iteration);
dhaupin
7

Suponiendo que desea eliminar el parámetro key = val del URI:

function removeParam(uri) {
   return uri.replace(/([&\?]key=val*$|key=val&|[?&]key=val(?=#))/, '');
}
ssh_imov
fuente
Funciona bien, pero escapar del primer signo de interrogación en la expresión regular es innecesario y puede causar un error de linter: /([&?]key=val*$|key=val&|[?&]key=val(?=#))/puede ser preferible cuando se usa un linter como eslint
quetzaluz
6

Heres una función completa para agregar y eliminar parámetros en función de esta pregunta y este github gist: https://gist.github.com/excalq/2961415

var updateQueryStringParam = function (key, value) {

    var baseUrl = [location.protocol, '//', location.host, location.pathname].join(''),
        urlQueryString = document.location.search,
        newParam = key + '=' + value,
        params = '?' + newParam;

    // If the "search" string exists, then build params from it
    if (urlQueryString) {

        updateRegex = new RegExp('([\?&])' + key + '[^&]*');
        removeRegex = new RegExp('([\?&])' + key + '=[^&;]+[&;]?');

        if( typeof value == 'undefined' || value == null || value == '' ) { // Remove param if value is empty

            params = urlQueryString.replace(removeRegex, "$1");
            params = params.replace( /[&;]$/, "" );

        } else if (urlQueryString.match(updateRegex) !== null) { // If param exists already, update it

            params = urlQueryString.replace(updateRegex, "$1" + newParam);

        } else { // Otherwise, add it to end of query string

            params = urlQueryString + '&' + newParam;

        }

    }
    window.history.replaceState({}, "", baseUrl + params);
};

Puede agregar parámetros como este:

updateQueryStringParam( 'myparam', 'true' );

Y eliminarlo así:

updateQueryStringParam( 'myparam', null );

En este hilo, muchos dijeron que la expresión regular probablemente no sea la mejor / solución estable ... así que no estoy 100% seguro de si esto tiene algunos defectos, pero hasta donde lo probé, funciona bastante bien.

GDY
fuente
5

Esta es una versión limpia que elimina el parámetro de consulta con la clase de URL para los navegadores actuales:

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

URLSearchParams no es compatible con navegadores antiguos

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

IE, Edge (menos de 17) y Safari (menos de 10.3) no admiten URLSearchParams dentro de la clase de URL.

Polyfills

URLSearchParams solo polyfill

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

Complete Polyfill URL y URLSearchParams para que coincidan con las últimas especificaciones WHATWG

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

Heroselohim
fuente
4

Usando jQuery:

function removeParam(key) {
    var url = document.location.href;
    var params = url.split('?');
    if (params.length == 1) return;

    url = params[0] + '?';
    params = params[1];
    params = params.split('&');

    $.each(params, function (index, value) {
        var v = value.split('=');
        if (v[0] != key) url += value + '&';
    });

    url = url.replace(/&$/, '');
    url = url.replace(/\?$/, '');

    document.location.href = url;
}
Huy Phạm
fuente
3

La versión anterior como una función

function removeURLParam(url, param)
{
 var urlparts= url.split('?');
 if (urlparts.length>=2)
 {
  var prefix= encodeURIComponent(param)+'=';
  var pars= urlparts[1].split(/[&;]/g);
  for (var i=pars.length; i-- > 0;)
   if (pars[i].indexOf(prefix, 0)==0)
    pars.splice(i, 1);
  if (pars.length > 0)
   return urlparts[0]+'?'+pars.join('&');
  else
   return urlparts[0];
 }
 else
  return url;
}
Graham
fuente
2

Debería usar una biblioteca para realizar la manipulación de URI, ya que es más complicado de lo que parece en la superficie hacerlo usted mismo. Echa un vistazo a: http://medialize.github.io/URI.js/

Ryan
fuente
2

Por lo que puedo ver, ninguno de los anteriores puede manejar parámetros normales y parámetros de matriz. Aquí hay uno que sí.

function removeURLParameter(param, url) {
    url = decodeURI(url).split("?");
    path = url.length == 1 ? "" : url[1];
    path = path.replace(new RegExp("&?"+param+"\\[\\d*\\]=[\\w]+", "g"), "");
    path = path.replace(new RegExp("&?"+param+"=[\\w]+", "g"), "");
    path = path.replace(/^&/, "");
    return url[0] + (path.length
        ? "?" + path
        : "");
}

function addURLParameter(param, val, url) {
    if(typeof val === "object") {
        // recursively add in array structure
        if(val.length) {
            return addURLParameter(
                param + "[]",
                val.splice(-1, 1)[0],
                addURLParameter(param, val, url)
            )
        } else {
            return url;
        }
    } else {
        url = decodeURI(url).split("?");
        path = url.length == 1 ? "" : url[1];
        path += path.length
            ? "&"
            : "";
        path += decodeURI(param + "=" + val);
        return url[0] + "?" + path;
    }
}

Cómo usarlo:

url = location.href;
    -> http://example.com/?tags[]=single&tags[]=promo&sold=1

url = removeURLParameter("sold", url)
    -> http://example.com/?tags[]=single&tags[]=promo

url = removeURLParameter("tags", url)
    -> http://example.com/

url = addURLParameter("tags", ["single", "promo"], url)
    -> http://example.com/?tags[]=single&tags[]=promo

url = addURLParameter("sold", 1, url)
    -> http://example.com/?tags[]=single&tags[]=promo&sold=1

Por supuesto, para actualizar un parámetro, simplemente elimine y luego agregue. Siéntase libre de hacer una función ficticia para ello.

Keir Simmons
fuente
path.replace(new RegExp("&?"+param+"=[\\w]+", "g"), "");Cambiaría la expresión regular para [\\w]*incluir parámetros como "param =" sin valores.
Tomas Prado
2

Todas las respuestas en este hilo tienen una falla en el sentido de que no conservan partes ancladas / fragmentadas de las URL.

Entonces, si su URL se ve así:

http://dns-entry/path?parameter=value#fragment-text

y reemplazas 'parámetro'

perderás tu fragmento de texto.

La siguiente es la adaptación de respuestas anteriores (bobince a través de LukePH) que aborda este problema:

function removeParameter(url, parameter)
{
  var fragment = url.split('#');
  var urlparts= fragment[0].split('?');

  if (urlparts.length>=2)
  {
    var urlBase=urlparts.shift(); //get first part, and remove from array
    var queryString=urlparts.join("?"); //join it back up

    var prefix = encodeURIComponent(parameter)+'=';
    var pars = queryString.split(/[&;]/g);
    for (var i= pars.length; i-->0;) {               //reverse iteration as may be destructive
      if (pars[i].lastIndexOf(prefix, 0)!==-1) {   //idiom for string.startsWith
        pars.splice(i, 1);
      }
    }
    url = urlBase + (pars.length > 0 ? '?' + pars.join('&') : '');
    if (fragment[1]) {
      url += "#" + fragment[1];
    }
  }
  return url;
}
Bret Weinraub
fuente
1
Mejora leve, de modo que cuando se elimina el parámetro de URL final, el '?' también se elimina: cambia la línea url = urlBase+'?'+pars.join('&');aurl = urlBase + (pars.length > 0 ? '?' + pars.join('&') : "");
Cody S
¿Qué pasa si # es lo primero? dns-entry / path # fragment-text? parameter = value
ajayv
2

Aquí una solución que:

  1. usa URLSearchParams (no es difícil entender la expresión regular)
  2. actualiza la URL en la barra de búsqueda sin recargar
  3. mantiene todas las otras partes de la URL (por ejemplo, hash)
  4. elimina superflous? en la cadena de consulta si se eliminó el último parámetro
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);
    }
}

Nota: como se señaló en otras respuestas, URLSearchParams no es compatible con IE , por lo tanto, use un polyfill .

klues
fuente
2

Si es una instancia de URL, use la deletefunción desearchParams

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

otra respuesta directa y más simple sería

let url = new URLSearchParams(location.search)
let key = 'some_key'

return url.has(key)
    ? location.href.replace(new RegExp(`[?&]${key}=${url.get(key)}`), '')
    : location.href
ctf0
fuente
0

Una versión modificada de la solución por ssh_imov

function removeParam(uri, keyValue) {
      var re = new RegExp("([&\?]"+ keyValue + "*$|" + keyValue + "&|[?&]" + keyValue + "(?=#))", "i"); 
      return uri.replace(re, '');
    }

Llama asi

removeParam("http://google.com?q=123&q1=234&q2=567", "q1=234");
// returns http://google.com?q=123&q2=567
kiranvj
fuente
Una cosa a tener en cuenta al enviar el valor del espacio de conversión param a% 20
xeon zolt
0

Esto devuelve la URL sin CUALQUIER parámetro de OBTENCIÓN:

var href = document.location.href;
var search = document.location.search;
var pos = href.indexOf( search );
if ( pos !== -1 ){
    href = href.slice( 0, pos );
    console.log( href );
}
David Freimaucher
fuente
0

Prácticamente escribí la siguiente función para procesar los parámetros de URL y obtener el estado final como una cadena y redirigir la página. Ojalá se beneficie.

function addRemoveUrlQuery(addParam = {}, removeParam = [], startQueryChar = '?'){

    let urlParams = new URLSearchParams(window.location.search);

    //Add param
    for(let i in addParam){
        if(urlParams.has(i)){ urlParams.set(i, addParam[i]); }
        else                { urlParams.append(i, addParam[i]); }
    }

    //Remove param
    for(let i of removeParam){
        if(urlParams.has(i)){
            urlParams.delete(i);
        }
    }

    if(urlParams.toString()){
        return startQueryChar + urlParams.toString();
    }

    return '';
}

Por ejemplo, cuando hago clic en un botón, quiero que se elimine el valor de la página y se agregue el valor de la categoría.

let button = document.getElementById('changeCategory');
button.addEventListener('click', function (e) {

    window.location = addRemoveUrlQuery({'category':'cars'}, ['page']);

});

¡Creo que fue muy útil!

Emrah Tuncel
fuente
0

Me alegra que te hayas desplazado aquí.

Le sugiero que resuelva esta tarea con las siguientes soluciones posibles:

  1. Debe admitir solo los navegadores modernos (Edge> = 17): use la API URLSearchParams.delete () . Es nativo y obviamente es la forma más conveniente de resolver esta tarea.
  2. Si esto no es una opción, puede escribir una función para hacerlo. Tal función hace
    • no cambie la URL si un parámetro no está presente
    • eliminar el parámetro URL sin un valor, como http://google.com/?myparm
    • eliminar el parámetro URL con un valor, como http://google.com/?myparm=1
    • eliminar el parámetro URL si está en la URL dos veces, como http://google.com?qp=1&qpqp=2&qp=1
    • No usa el forbucle y no modifica la matriz durante el bucle sobre él
    • es más funcional
    • es más legible que las soluciones regexp
    • Antes de usar, asegúrese de que su URL no esté codificada

Funciona en IE> 9 (versión ES5)

function removeParamFromUrl(url, param) {  // url: string, param: string
  var urlParts = url.split('?'),
      preservedQueryParams = '';

  if (urlParts.length === 2) {
    preservedQueryParams = urlParts[1]
      .split('&')
      .filter(function(queryParam) {
        return !(queryParam === param || queryParam.indexOf(param + '=') === 0)
      })
      .join('&');
  }

  return urlParts[0] +  (preservedQueryParams && '?' + preservedQueryParams); 
}

Fancy ES6 versión

function removeParamFromUrlEs6(url, param) {
  const [path, queryParams] = url.split('?');
	let preservedQueryParams = '';

  if (queryParams) {
    preservedQueryParams = queryParams
      .split('&')
      .filter(queryParam => !(queryParam === param || queryParam.startsWith(`${param}=`)))
      .join('&');
  }

  return `${path}${preservedQueryParams && `?${preservedQueryParams}`}`;  
}

Mira cómo funciona aquí

Shevchenko Viktor
fuente
0
function removeParamInAddressBar(parameter) {
    var url = document.location.href;
    var urlparts = url.split('?');

    if (urlparts.length >= 2) {
        var urlBase = urlparts.shift();
        var queryString = urlparts.join("?");

        var prefix = encodeURIComponent(parameter) + '=';
        var pars = queryString.split(/[&;]/g);
        for (var i = pars.length; i-- > 0;) {
            if (pars[i].lastIndexOf(prefix, 0) !== -1) {
                pars.splice(i, 1);
            }
        }

        if (pars.length == 0) {
            url = urlBase;
        } else {
            url = urlBase + '?' + pars.join('&');
        }

        window.history.pushState('', document.title, url); // push the new url in address bar
    }
    return url;
}
Alex
fuente
-1
const params = new URLSearchParams(location.search)
params.delete('key_to_delete')
console.log(params.toString())
Neeraj Pathak
fuente
Esta es una respuesta a una pregunta que es muy antigua y ya tiene una respuesta aceptada. Por favor explique lo que esta respuesta tiene para ofrecer, que es nuevo / diferente de las otras respuestas. Además, las respuestas deben incluir explicaciones y no solo código.
nurdyguy
-2
function removeQueryStringParameter(uri, key, value) 
{

var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");

    var separator = uri.indexOf('?') !== -1 ? "&" : "?";

    if (uri.match(re)) {

        return uri.replace(re, '');

    }
}
Prasad Patil
fuente