Como posso excluir um parâmetro de string de consulta em JavaScript?

127

Existe uma maneira melhor de excluir um parâmetro de uma string de consulta em uma string de URL no JavaScript padrão que não seja usando uma expressão regular?

Aqui está o que eu criei até agora, que parece funcionar nos meus testes, mas não gosto de reinventar a análise da string 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
fonte

Respostas:

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

Parece perigoso porque seu parâmetro 'bar' corresponderia:

?a=b&foobar=c

Além disso, falharia se parametercontivesse caracteres especiais no RegExp, como '.'. E não é um regex global, portanto, ele removeria apenas uma instância do parâmetro.

Eu não usaria um RegExp simples para isso, analisaria os parâmetros e perderia os que você não deseja.

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
fonte
Bom ponto sobre a barra correspondente ao foobar. Atualizei minha regex original para exigir uma? ou um [&;] no início. Também ler sobre sua solução para considerá-lo ...
Matthew Bloqueio
5
Se você quer se livrar do "?" quando não houver parâmetros após a remoção, adicione uma condição if para testar se pars.length == 0 e, se for 0, faça "url = urlparts [0]" em vez de anexar o "?".
johnmcaliley
2
É seguro comparar o fragmento de URL com encodeURIComponent (parâmetro)? E se o URL codificar o nome do parâmetro de maneira diferente? Por exemplo 'two% 20words' versus 'two + words'. Para lidar com isso, talvez seja melhor decodificar o nome do parâmetro e compará-lo como uma sequência normal.
Adrian Pronk
9
Aperfeiçoamento leve, para que, quando o Parâmetro final do URL for removido, o '?' também é removido: Altere a linha url= urlparts[0]+'?'+pars.join('&');paraurl= urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : "");
Cody S
2
Os parâmetros de consulta de URL @ ktutnik / @ JonasAxelsson não fazem distinção entre maiúsculas e minúsculas.
bobince
30

Navegadores modernos fornecem URLSearchParamsinterface para trabalhar com parâmetros de pesquisa. Que possui um deletemétodo que remove o parâmetro pelo nome.

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
fonte
2
Observe que URLSearchParamsnão há suporte para o IE, Edge 16 e iOS 10.2 Safari. (ref: caniuse.com/#feat=urlsearchparams )
khiav reoy
3
@khiavreoy Yeah. Como as duas primeiras palavras a resposta dar o mesmo link :)
Yury Tarabanko
23

Copiado da resposta bobince, mas suportou pontos de interrogação na string de consulta, por exemplo

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

É válido ter mais de um ponto de interrogação em um 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
fonte
2
Acredito que a ???sintaxe é inválida e nunca deve ocorrer em um URL`.
@torazaburo Dê uma olhada na pergunta do stackoverflow que eu postei: "É válido ter mais de um ponto de interrogação em um URL?", a resposta parece ser sim. Também isso foi há anos, então não consigo me lembrar dos detalhes, mas tive problemas quando isso não foi tratado corretamente.
LukePH 24/09
Não estou dizendo que eles não existem no mundo real, e provavelmente seria possível lidar com eles, mas em um URL formado corretamente, o ponto de interrogação é um "caractere reservado" e qualquer ponto de interrogação diferente daquele a introdução dos parâmetros de consulta deve ser codificada em URL.
1
Convém substituir a última linha por return url.endsWith("?") ? url.slice(0,-1) : url;para cobrir o caso em que o parâmetro a ser removido é o único na sequência de consultas
Konamiman
@ Konamiman Isso alteraria os dados dos parâmetros ao remover, por exemplo, 'aq' de: google.com/search?q=test???&aq=f, mas entendi o que você quer dizer com isso, seria bom limpar o URL, mesmo que o ? não faz mal nenhum. A lógica só precisa ter certeza do último? também é o primeiro?
LukePH
21

Não vejo grandes problemas com uma solução regex. Mas, não esqueça de preservar o identificador de fragmento (texto após o #).

Aqui está a minha solução:

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

E ao ponto de bobince, sim - você precisaria escapar .caracteres nos nomes de parâmetros.

Jared
fonte
1
Aqui está um regex aprimorado que funciona quando o paramater não tem valor (por exemplo, 'ex.com?removeMe') e não substitui o parâmetro em fragmentos (por exemplo, 'ex.com?#&dont=removeMe') ou caminhos (por exemplo, ' ex.com/&dont=removeMe '):url.replace(new RegExp('^([^#]*\?)(([^#]*)&)?' + parameter + '(\=[^&#]*)?(&|#|$)' ), '$1$3$5').replace(/^([^#]*)((\?)&|\?(#|$))/,'$1$3$4')
Stephen M. Harris
Isso não vai funcionar Stephen M. Harris. Tente dar o seu código de uma String vazia como um param e ver o que acontece ...
David Fischer
15

Você pode alterar o URL com:

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

Dessa forma, você pode sobrescrever a URL sem o parâmetro de pesquisa, eu a uso para limpar a URL depois de pegar os parâmetros GET.

Santi Nunez
fonte
13

Qualquer pessoa interessada em uma solução regex, reuni essa função para adicionar / remover / atualizar um parâmetro de querystring. Não fornecer um valor removerá o parâmetro, fornecer um adicionará / atualizará o parâmetro. Se nenhum URL for fornecido, ele será acessado em window.location. Essa solução também leva em consideração a âncora do 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;
    }
}

ATUALIZAR

Ocorreu um erro ao remover o primeiro parâmetro na string de consulta, refiz o regex e testei para incluir uma correção.

ATUALIZAÇÃO 2

Atualização @schellmax para corrigir a situação em que o símbolo da hashtag é perdido ao remover uma variável da string de consulta diretamente antes de uma hashtag

ellemayo
fonte
1
Isso não funciona se você tiver duas cadeias de consulta e remover a primeira. O URL passado é inválido porque o? é removido quando deve ser preservado.
Blake Niemyjski 6/03/2013
1
@BlakeNiemyjski graças para encontrar esse erro, eu atualizei o script para incluir uma solução alternativa para o primeiro parâmetro
ellemayo
1
acidentalmente removerá o hash aqui:UpdateQueryString('a', null, 'http://www.test.com?a=b#c');
schellmax 13/13
Função legal, obrigado. FYI: enquanto estiver usando isso com um ignorar chaves de array em cada loop () `, pode ser necessário definir um encolhimento urlpara cada iteração de substituição. Mas isso significa que você deve inserir um valuenos argumentos, o que deixará a cadeia de consulta removida pela metade. Para contrariar esta situação, o uso undefinedou nullpara valueargumento como:url_from_last_iteration = UpdateQueryString(current_ignore_key, undefined/null, url_from_last_iteration);
dhaupin
7

Supondo que você deseja remover o parâmetro key = val do URI:

function removeParam(uri) {
   return uri.replace(/([&\?]key=val*$|key=val&|[?&]key=val(?=#))/, '');
}
ssh_imov
fonte
Funciona bem, mas escapar o primeiro ponto de interrogação no regex é desnecessária e pode causar linter de erro: /([&?]key=val*$|key=val&|[?&]key=val(?=#))/pode ser preferível quando se utiliza um linter como eslint
quetzaluz
7

Aqui está o que estou usando:

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

URL original: http://www.example.com/test/hello?id=123&foo=bar
URL de destino: http://www.example.com/test/hello

Basj
fonte
Você escreve esse código no carregamento da página? Estou perguntando, porque quando estou escrevendo esse carregamento de página ou não, ele não funciona.
noobprogrammer
6

Heres uma função completa para adicionar e remover parâmetros com base nesta questão e neste github gistub: 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);
};

Você pode adicionar parâmetros como este:

updateQueryStringParam( 'myparam', 'true' );

E remova-o assim:

updateQueryStringParam( 'myparam', null );

Neste tópico, muitos disseram que o regex provavelmente não é a melhor solução / estável ... por isso não tenho 100% de certeza se essa coisa tem algumas falhas, mas tanto quanto eu a testei, ela funciona muito bem.

GDY
fonte
5

Esta é uma versão limpa, remover o parâmetro de consulta com a classe URL dos navegadores atuais:

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

URLSearchParams não suportado em navegadores antigos

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

O IE, Edge (abaixo de 17) e Safari (abaixo de 10.3) não suportam URLSearchParams dentro da classe de URL.

Polyfills

URLSearchParams apenas polyfill

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

URL completo do Polyfill e URLSearchParams para corresponder às últimas especificações do WHATWG

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

Heroselohim
fonte
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
fonte
3

A versão acima como uma função

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
fonte
2

Você deve usar uma biblioteca para fazer manipulação de URI, pois é mais complicado do que parece na superfície fazer você mesmo. Dê uma olhada em: http://medialize.github.io/URI.js/

Ryan
fonte
2

Pelo que posso ver, nenhuma das opções acima pode lidar com parâmetros normais e parâmetros de matriz. Aqui está um que faz.

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

Como usá-lo:

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

Obviamente, para atualizar um parâmetro, basta remover e adicionar. Sinta-se livre para criar uma função fictícia para ele.

Keir Simmons
fonte
path.replace(new RegExp("&?"+param+"=[\\w]+", "g"), "");Eu mudaria o regex para [\\w]*incluir parâmetros como "param =" sem valores.
Tomas Prado
2

Todas as respostas neste segmento têm uma falha, pois não preservam partes de âncora / fragmento de URLs.

Portanto, se o seu URL se parecer com:

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

e você substitui 'parâmetro'

você perderá o texto do fragmento.

A seguir está a adaptação de respostas anteriores (bobince via LukePH) que abordam esse 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
fonte
1
Aperfeiçoamento leve, para que, quando o Parâmetro final do URL for removido, o '?' também é removido: Altere a linha url = urlBase+'?'+pars.join('&');paraurl = urlBase + (pars.length > 0 ? '?' + pars.join('&') : "");
Cody S
2

Aqui está uma solução que:

  1. usa URLSearchParams (não é difícil entender regex)
  2. atualiza o URL na barra de pesquisa sem recarregar
  3. mantém todas as outras partes da URL (por exemplo, hash)
  4. remove supérfluo? na string de consulta se o último parâmetro foi removido
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: conforme indicado em outras respostas, o URLSearchParams não é suportado no IE , portanto, use um polyfill .

klues
fonte
2

Se for uma instância de URL, use a deletefunção desearchParams

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

outra resposta direta e mais simples seria

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
fonte
0

Uma versão modificada da solução por ssh_imov

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

Ligue assim

removeParam("http://google.com?q=123&q1=234&q2=567", "q1=234");
// returns http://google.com?q=123&q2=567
kiranvj
fonte
uma coisa a ter em mente ao enviar o valor do parâmetro param converter espaço em% 20
xeon zolt
0

Isso retorna a URL sem quaisquer parâmetros GET:

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
fonte
0

Eu praticamente escrevi a seguinte função para processar os parâmetros de URL e obter o status final como uma string e redirecionar a página. Espero que seja benéfico.

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 exemplo, quando clico em um botão, desejo que o valor da página seja excluído e o valor da categoria seja adicionado.

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

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

});

Eu acho que foi muito útil!

Emrah Tuncel
fonte
0

Que bom que você rolou aqui.

Sugiro que você resolva esta tarefa com as próximas soluções possíveis:

  1. Você precisa oferecer suporte apenas a navegadores modernos (Edge> = 17) - use a API URLSearchParams.delete () . É nativo e, obviamente, é a maneira mais conveniente de resolver esta tarefa.
  2. Se isso não for uma opção, você pode escrever uma função para fazer isso. Essa função faz
    • não altere o URL se um parâmetro não estiver presente
    • remova o parâmetro de URL sem um valor, como http://google.com/?myparm
    • remova o parâmetro URL com um valor, como http://google.com/?myparm=1
    • remova o parâmetro URL se ele estiver no URL duas vezes, como http://google.com?qp=1&qpqp=2&qp=1
    • Não usa forloop e não modifica o array durante o loop sobre ele
    • é mais funcional
    • é mais legível que as soluções regexp
    • Antes de usar, verifique se o seu URL não está codificado

Funciona no IE> 9 (versão 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); 
}

Versão ES6 extravagante

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

Veja como funciona aqui

Shevchenko Viktor
fonte
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
fonte
-1
const params = new URLSearchParams(location.search)
params.delete('key_to_delete')
console.log(params.toString())
Neeraj Pathak
fonte
Esta é uma resposta a uma pergunta que é muito antiga e já tem uma resposta aceita. Explique o que esta resposta tem a oferecer, que é nova / diferente das outras respostas. Além disso, as respostas devem incluir explicações e não apenas código.
Nurdyguy 29/10/19
-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
fonte