Como criar uma string de consulta com Javascript

Respostas:

-24

Eu tentei procurar uma resposta para essa pergunta há algum tempo, mas acabei escrevendo minha própria função que extrai os valores do formulário.

não é perfeito, mas atende às minhas necessidades.

function form_params( form )
{
    var params = new Array()
    var length = form.elements.length
    for( var i = 0; i < length; i++ )
    {
        element = form.elements[i]

        if(element.tagName == 'TEXTAREA' )
        {
            params[element.name] = element.value
        }
        else if( element.tagName == 'INPUT' )
        {
            if( element.type == 'text' || element.type == 'hidden' || element.type == 'password')
            {
                params[element.name] = element.value
            }
            else if( element.type == 'radio' && element.checked )
            {
                if( !element.value )
                    params[element.name] = "on"
                else
                    params[element.name] = element.value

            }
            else if( element.type == 'checkbox' && element.checked )
            {
                if( !element.value )
                    params[element.name] = "on"
                else
                    params[element.name] = element.value
            }
        }
    }
    return params;
}

form_params retorna um mapeamento (chave -> valor) dos parâmetros. a entrada é o elemento do formulário (elemento DOM)

Ele não trata de campos que permitem seleção múltipla.

hasen
fonte
44
Sou apenas eu ou isso não responde à pergunta? Ele estava pedindo uma string de consulta, não uma matriz mapeada.
Jake Wilson
2
@JakeWilson Sim, essa resposta apenas metade responde à pergunta. A matriz ainda precisa entrar em um formato de string de consulta.
Hutch Moore 26/05
8
uau, eu devia ter sido um noob no JS naquela época. Usando new Array()para inicializar um dicionário. Mas, novamente, o código parece muito mais limpo do que algumas porcarias que eu escreveria nos dias de hoje!
hasen
2
@ talvez você considere editar esta resposta ou, bem, excluí-la? Tem cada vez mais votos negativos cada vez que eu rolar para ele = -D (eu até me lembro da hora em que tinha uma proporção positiva ...)
Klesun
1
@ArturKlesun sim, não. Eu não ligo Você pode tentar pedir à pessoa que fez a pergunta que não aceite esta resposta.
hasen
220

Atualização 2k20: use a solução de Josh com URLSearchParams.toString () .

Resposta antiga:


Sem jQuery

var params = {
    parameter1: 'value_1',
    parameter2: 'value 2',
    parameter3: 'value&3' 
};

var esc = encodeURIComponent;
var query = Object.keys(params)
    .map(k => esc(k) + '=' + esc(params[k]))
    .join('&');

Para navegadores que não suportam a sintaxe da função de seta que requer ES5, altere o .map... linha para

    .map(function(k) {return esc(k) + '=' + esc(params[k]);})
Klesun
fonte
8
Melhor solução que eu já vi - muito limpa e concisa. Algumas advertências, no entanto. 1) no .map (), k e params [k] devem ser codificados, por exemplo, encodeURIComponent (k) e encodeURIComponent (params [k]). 2) Você tem permissão para ter mais de uma instância de um parâmetro nomeado em uma string de consulta. Se você deseja esse recurso, precisará usar uma matriz em vez de um objeto (a maioria dos aplicativos não deseja ou precisa disso).
precisa saber é o seguinte
9
3) Nem todos os navegadores suportam a sintaxe da função de seta (que requer o ES5). Se você deseja oferecer suporte a todos os navegadores (e codificar as partes), substitua o .map () acima por .map (função (k) {retorne encodeURIComponent (k) + '=' + encodeURIComponent (params [k]);})
precisa saber é o seguinte
1
Lindo. Verdadeiramente bonito.
Mikko Ohtamaa
9
"não é suficiente jquery"
Eugene Pankov 10/02
1
@ user1738579 Editei a resposta para também incluir seu exemplo para não ES5.
Taylor Edmiston
134

Se você estiver usando o jQuery, poderá consultar jQuery.param() http://api.jquery.com/jQuery.param/

Exemplo:

var params = {
    parameter1: 'value1',
    parameter2: 'value2',
    parameter3: 'value3' 
};
var query = $.param(params);
document.write(query);
Klemen Tušar
fonte
13
Esta é realmente a resposta correta! A sequência de consultas para um formulário é $.param($('#myform').serializeArray()).
Jesse
7
@ Jessé, isso seria o mesmo resultado que:$('#myform').serialize()
cutelo
94
jQuery !== JavaScript
Gphilip # /
14
@ gphilip Bem, é por isso que eu comecei a resposta com "Se você estiver usando jQuery ...". Caso contrário, se você quiser implementá-lo em baunilha JS você pode examinar a implementação de jQuery.param()aqui github.com/jquery/jquery/blob/master/src/serialize.js :)
Klemen Tušar
2
Ao contrário da minha resposta, esta suporta objetos aninhados comosomeStr=value1&someObj[a]=5&someObj[b]=6&someArr[]=1&someArr[]=2
Klesun 25/10/18
113

A API URLSearchParams está disponível em todos os navegadores modernos. Por exemplo:

const params = new URLSearchParams({
  var1: "value",
  var2: "value2",
  arr: "foo",
});
console.log(params.toString());
//Prints "var1=value&var2=value2&arr=foo"

Josh
fonte
3
Melhor resposta aqui imo. Apenas para adicionar a isso, você pode fazer params.append(key, value)mais tarde adicionando novos parâmetros de pesquisa em cenários mais complicados.
Mingwei Zhang
4
Observe que valores nulos e indefinidos estão incluídos na sequência final:x=null&y=undefined
pomber
2
Além disso, se você já possui um objeto de URL (por exemplo const url = new URL("https://stackoverflow.com")), pode definir suas cadeias de consulta url.search = new URLSearchParams({foo: "bar"})ouurl.searchParams.append("foo", "bar")
Miguel Pynto
Observe que o TS avisa sobre o uso de um objeto simples, mas, mesmo assim, funciona bem
Vadorequest
@pomber Alguma boa idéia sobre como filtrar esses itens indefinidos?
Dan Gayle
53

Isso não responde diretamente à sua pergunta, mas aqui está uma função genérica que criará um URL que contém parâmetros de string de consulta. Os parâmetros (nomes e valores) são escapados com segurança para inclusão em uma URL.

function buildUrl(url, parameters){
  var qs = "";
  for(var key in parameters) {
    var value = parameters[key];
    qs += encodeURIComponent(key) + "=" + encodeURIComponent(value) + "&";
  }
  if (qs.length > 0){
    qs = qs.substring(0, qs.length-1); //chop off last "&"
    url = url + "?" + qs;
  }
  return url;
}

// example:
var url = "http://example.com/";

var parameters = {
  name: "George Washington",
  dob: "17320222"
};

console.log(buildUrl(url, parameters));
// => http://www.example.com/?name=George%20Washington&dob=17320222
Michael
fonte
1
Existe alguma função interna semelhante a essa em um dos frameworks javascript populares como jquery, mootools, etc ...?
Samuel
Uma solução JavaScript nativa mais robusto está em stackoverflow.com/a/1714899/1269037
Dan Dascalescu
A implementação mais estranha de todas, por que você precisa inicializar um new Arraypouco enquanto realmente a usa como objeto? o, O
Umut Sirin
@UmutSirin Lol sim, eu não sabia muito sobre Javascript na época. xD Eu acho que estava tratando como uma matriz PHP. Sinta-se livre para refatorar, se quiser.
Michael
@ Michael Haha, sim. Acabei de enviar uma edição. Obrigado pela resposta!
Umut Sirin
22

Com o jQuery, você pode fazer isso $.param

$.param({ action: 'ship', order_id: 123, fees: ['f1', 'f2'], 'label': 'a demo' })

// -> "action=ship&order_id=123&fees%5B%5D=f1&fees%5B%5D=f2&label=a+demo"
manish_s
fonte
17

ES2017 (ES8)

Fazendo uso de Object.entries(), que retorna uma matriz de [key, value]pares de objetos . Por exemplo, {a: 1, b: 2}pois retornaria [['a', 1], ['b', 2]]. Não é suportado (e não será) apenas pelo IE.

Código:

const buildURLQuery = obj =>
      Object.entries(obj)
            .map(pair => pair.map(encodeURIComponent).join('='))
            .join('&');

Exemplo:

buildURLQuery({name: 'John', gender: 'male'});

Resultado:

"name=John&gender=male"
Przemek
fonte
10

Não, eu não acho que o JavaScript padrão tenha isso incorporado, mas o Prototype JS tem essa função (certamente a maioria das outras estruturas JS também, mas eu não as conheço), eles chamam de serializar .

Posso recomendar o Prototype JS, funciona bastante bem. A única desvantagem que eu realmente notei é o tamanho (algumas centenas de kb) e o escopo (muito código para ajax, dom etc.). Portanto, se você quer apenas um serializador de formulários, é um exagero e, estritamente falando, se você quer apenas a funcionalidade Ajax (que é principalmente o que eu usei), é um exagero. A menos que você seja cuidadoso, poderá achar que ele faz um pouco de "mágica" (como estender cada elemento dom que toca nas funções Prototype JS apenas para encontrar elementos), tornando-o lento em casos extremos.

Stein G. Strindhaug
fonte
Basta saber se há algo embutido. Parece que deveria haver. Eu odeio protótipo, mas eu não estou segurando isso contra você :)
Quando o JavaScript foi projetado, o Ajax ainda não foi descoberto, portanto, analisando um formulário apenas para obter a sequência de consultas (que seria criada quando enviada) provavelmente não fazia muito sentido. Hoje sim, difícil ... Aliás, comparado ao script.aculo.us, o protótipo é bom . :)
Stein G. Strindhaug
10

querystring pode ajudar.

Então você pode

const querystring = require('querystring')

url += '?' + querystring.stringify(parameters)
Eu sou leo
fonte
3
Para aplicações de frontend você também pode considerar npmjs.com/package/qs
Robert Pankowecki
@RobertPankowecki, sim, qs é melhor e já está no meu arsenal, felicidades!
ImLeo
6

Se você não quiser usar uma biblioteca, isso deve cobrir a maioria dos tipos de elementos de formulário.

function serialize(form) {
  if (!form || !form.elements) return;

  var serial = [], i, j, first;
  var add = function (name, value) {
    serial.push(encodeURIComponent(name) + '=' + encodeURIComponent(value));
  }

  var elems = form.elements;
  for (i = 0; i < elems.length; i += 1, first = false) {
    if (elems[i].name.length > 0) { /* don't include unnamed elements */
      switch (elems[i].type) {
        case 'select-one': first = true;
        case 'select-multiple':
          for (j = 0; j < elems[i].options.length; j += 1)
            if (elems[i].options[j].selected) {
              add(elems[i].name, elems[i].options[j].value);
              if (first) break; /* stop searching for select-one */
            }
          break;
        case 'checkbox':
        case 'radio': if (!elems[i].checked) break; /* else continue */
        default: add(elems[i].name, elems[i].value); break;
      }
    }
  }

  return serial.join('&');
}
Jonathan Lonowski
fonte
Obrigado! Eu estava enfrentando o mesmo problema que o pôster original e sua função era exatamente o que eu precisava.
224 dagw
4

Na verdade, você não precisa de um formulário para fazer isso com o Prototype. Basta usar a função Object.toQueryString :

Object.toQueryString({ action: 'ship', order_id: 123, fees: ['f1', 'f2'], 'label': 'a demo' })

// -> 'action=ship&order_id=123&fees=f1&fees=f2&label=a%20demo'
Thibaut Barrère
fonte
4
Concedido, você respondeu há quase 10 anos, mas este código está obsoleto.
SEoF 02/10/19
4

Hoje em dia, você pode fazer isso com FormDatae URLSearchParamssem a necessidade de repetir qualquer coisa.

const formData = new FormData(form);
const searchParams = new URLSearchParams(formData);
const queryString = searchParams.toString();

Os navegadores mais antigos precisarão de um polyfill.

Björn Tantau
fonte
3

Não tenho muita certeza, lembro-me de ter visto o jQuery até certo ponto, mas ele não lida com registros hierárquicos, muito menos de uma maneira amigável para php.

Uma coisa que eu tenho certeza é que, ao criar URLs e colar o produto no dom, não use cola para fazer isso, ou você estará se abrindo para um prático quebra de página.

Por exemplo, certos softwares de publicidade alinham a string da versão do que quer que seja executado no seu flash. Isso é bom quando sua string simples genérica adobra, mas, no entanto, é muito ingênua e explode em uma confusão embaraçosa para pessoas que instalaram o Gnash, já que a string da versão do gnash'es contém uma licença completa de direitos autorais da GPL, completa com URLs e tags <a href>. Usando isso em seu gerador de anunciantes de cola em seqüência, a página é aberta e o HTML desequilibrado é exibido no domínio.

A moral da história:

   var foo = document.createElement("elementnamehere"); 
   foo.attribute = allUserSpecifiedDataConsideredDangerousHere; 
   somenode.appendChild(foo); 

Não:

   document.write("<elementnamehere attribute=\"" 
        + ilovebrokenwebsites 
        + "\">" 
        + stringdata 
        + "</elementnamehere>");

O Google precisa aprender esse truque. Eu tentei relatar o problema, eles parecem não se importar.

Kent Fredric
fonte
Pode apostar. Document.write é tão 1995, enfim.
2

Como Stein diz, você pode usar a biblioteca javascript prototype em http://www.prototypejs.org . Inclua o JS e é muito simples então, $('formName').serialize()retornará o que você quer!

Shyam
fonte
2

Pode ser um pouco redundante, mas a maneira mais limpa que encontrei, baseada em algumas das respostas aqui:

const params: {
   key1: 'value1',
   key2: 'value2',
   key3: 'value3',
}

const esc = encodeURIComponent;
const query = Object.keys(params)
  .map(k => esc(k) + '=' + esc(params[k]))
  .join('&');

return fetch('my-url', {
  method: 'POST',
  headers: {'Content-Type': 'application/x-www-form-urlencoded'},
  body: query,
})

Fonte

David Pascoal
fonte
1

Essas respostas são muito úteis, mas quero adicionar outra resposta, que pode ajudá-lo a criar um URL completo. Isso pode ajudar você concat de base url, path, hashe parameters.

var url = buildUrl('http://mywebsite.com', {
        path: 'about',
        hash: 'contact',
        queryParams: {
            'var1': 'value',
            'var2': 'value2',
            'arr[]' : 'foo'
        }
    });
    console.log(url);

Você pode fazer o download via npm https://www.npmjs.com/package/build-url

Demo:

;(function () {
  'use strict';

  var root = this;
  var previousBuildUrl = root.buildUrl;

  var buildUrl = function (url, options) {
    var queryString = [];
    var key;
    var builtUrl;
    var caseChange; 
    
    // 'lowerCase' parameter default = false,  
    if (options && options.lowerCase) {
        caseChange = !!options.lowerCase;
    } else {
        caseChange = false;
    }

    if (url === null) {
      builtUrl = '';
    } else if (typeof(url) === 'object') {
      builtUrl = '';
      options = url;
    } else {
      builtUrl = url;
    }

    if(builtUrl && builtUrl[builtUrl.length - 1] === '/') {
      builtUrl = builtUrl.slice(0, -1);
    } 

    if (options) {
      if (options.path) {
          var localVar = String(options.path).trim(); 
          if (caseChange) {
            localVar = localVar.toLowerCase();
          }
          if (localVar.indexOf('/') === 0) {
              builtUrl += localVar;
          } else {
            builtUrl += '/' + localVar;
          }
      }

      if (options.queryParams) {
        for (key in options.queryParams) {
          if (options.queryParams.hasOwnProperty(key) && options.queryParams[key] !== void 0) {
            var encodedParam;
            if (options.disableCSV && Array.isArray(options.queryParams[key]) && options.queryParams[key].length) {
              for(var i = 0; i < options.queryParams[key].length; i++) {
                encodedParam = encodeURIComponent(String(options.queryParams[key][i]).trim());
                queryString.push(key + '=' + encodedParam);
              }
            } else {              
              if (caseChange) {
                encodedParam = encodeURIComponent(String(options.queryParams[key]).trim().toLowerCase());
              }
              else {
                encodedParam = encodeURIComponent(String(options.queryParams[key]).trim());
              }
              queryString.push(key + '=' + encodedParam);
            }
          }
        }
        builtUrl += '?' + queryString.join('&');
      }

      if (options.hash) {
        if(caseChange)
            builtUrl += '#' + String(options.hash).trim().toLowerCase();
        else
            builtUrl += '#' + String(options.hash).trim();
      }
    } 
    return builtUrl;
  };

  buildUrl.noConflict = function () {
    root.buildUrl = previousBuildUrl;
    return buildUrl;
  };

  if (typeof(exports) !== 'undefined') {
    if (typeof(module) !== 'undefined' && module.exports) {
      exports = module.exports = buildUrl;
    }
    exports.buildUrl = buildUrl;
  } else {
    root.buildUrl = buildUrl;
  }
}).call(this);


var url = buildUrl('http://mywebsite.com', {
		path: 'about',
		hash: 'contact',
		queryParams: {
			'var1': 'value',
			'var2': 'value2',
			'arr[]' : 'foo'
		}
	});
	console.log(url);

Hien Nguyen
fonte
1

Eu sei que esta é uma resposta muito tarde, mas funciona muito bem ...

var obj = {
a:"a",
b:"b"
}

Object.entries(obj).map(([key, val])=>`${key}=${val}`).join("&");

note: object.entries retornará chave, pares de valores

a saída acima da linha será a = a & b = b

Espero que ajude alguém.

Feliz codificação ...

ajaykumar mp
fonte
0

Provavelmente é tarde demais para responder à sua pergunta.
Eu tinha a mesma pergunta e não gostava de continuar anexando strings para criar um URL. Então, comecei a usar $ .param como explicado pela techhouse .
Encontrei também uma biblioteca URI.js que cria os URLs facilmente para você. Há vários exemplos que o ajudarão a: Documentação URI.js .
Aqui está um deles:

var uri = new URI("?hello=world");
uri.setSearch("hello", "mars"); // returns the URI instance for chaining
// uri == "?hello=mars"

uri.setSearch({ foo: "bar", goodbye : ["world", "mars"] });
// uri == "?hello=mars&foo=bar&goodbye=world&goodbye=mars"

uri.setSearch("goodbye", "sun");
// uri == "?hello=mars&foo=bar&goodbye=sun"

// CAUTION: beware of arrays, the following are not quite the same
// If you're dealing with PHP, you probably want the latter…
uri.setSearch("foo", ["bar", "baz"]);
uri.setSearch("foo[]", ["bar", "baz"]);`
SaraNa
fonte
0

var params = { width:1680, height:1050 };
var str = jQuery.param( params );

console.log(str)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Bashirpour
fonte