web-dev-qa-db-fra.com

Comment construire une chaîne de requête avec Javascript

Je me demandais simplement si quelque chose dans JavaScript pouvait prendre un formulaire et renvoyer les paramètres de la requête, par exemple: "var1 = valeur & var2 = valeur2 & arr [] = toto & arr [] = barre ..."

Je me le demande depuis des années.

133
John II

Sans 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('&');

Pour les navigateurs qui ne prennent pas en charge la syntaxe de la fonction de flèche nécessitant ES5, modifiez le paramètre .map... ligne à

    .map(function(k) {return esc(k) + '=' + esc(params[k]);})
184
Artur Klesun

Si vous utilisez jQuery, vous pouvez consulter jQuery.param()http://api.jquery.com/jQuery.param/

Exemple:

var params = {
    parameter1: 'value1',
    parameter2: 'value2',
    parameter3: 'value3' 
};
​var query = $.param(params);
document.write(query);
132
techouse

Cela ne répond pas directement à votre question, mais voici une fonction générique qui créera une URL contenant des paramètres de chaîne de requête. Les paramètres (noms et valeurs) sont protégés en toute sécurité pour être inclus dans une 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
54
Michael

Il existe maintenant des API pour cela, en particulier API URLSearchParams . Pour l'exemple donné:

const params = new URLSearchParams();
const formvals = {
   var1: "value",
   var2: "value2",
   arr: "foo",
};
for (const [key, val] of Object.entries(formvals)) {
   params.append(key, val);
}
console.log(params.toString());
// var1=value&var2=value2&arr=foo

Remarque: C'est très compatible avec Chrome et Firefox ces jours-ci, mais soyez prudent si vous avez besoin de travailler avec Microsoft et avec les navigateurs Apple puisque la compatibilité est partielle.

24
Josh

Avec jQuery, vous pouvez le faire en $.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"
21
manish_s

ES2017 (ES8)

En utilisant Object.entries() , qui retourne un tableau de l'objet [key, value] paires. Par exemple, pour {a: 1, b: 2} il reviendrait [['a', 1], ['b', 2]]. Il n'est pas supporté (et ne sera pas) uniquement par IE.

Code:

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

Exemple:

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

Résultat:

"name=John&gender=male"
12
Przemek

Non, je ne pense pas que le langage JavaScript standard soit intégré, mais Prototype JS a cette fonction (la plupart des autres frameworks JS le sont aussi, mais je ne les connais pas), ils l'appellent serialize .

Je peux recommander Prototype JS, cela fonctionne très bien. Le seul inconvénient que j’ai vraiment remarqué est sa taille (quelques centaines de ko) et son étendue (beaucoup de code pour ajax, dom, etc.). Ainsi, si vous ne voulez qu'un sérialiseur de formulaire, c'est une surcharge, et à proprement parler, si vous ne voulez que la fonctionnalité Ajax (qui est principalement ce pour quoi je l'ai utilisée), c'est une surcharge. Si vous ne faites pas attention, vous constaterez peut-être que cela fait un peu trop "magique" (comme d'étendre chaque élément du dom qu'il touche avec les fonctions Prototype JS juste pour trouver des éléments), ce qui le ralentit dans les cas extrêmes.

10

chaîne de requête peut vous aider.

Afin que vous puissiez

const querystring = require('querystring')

url += '?' + querystring.stringify(parameters)
7
ImLeo

Si vous ne souhaitez pas utiliser une bibliothèque, cela devrait couvrir la plupart/tous les mêmes types d'élément de formulaire.

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('&');
}
6
Jonathan Lonowski

En fait, vous n’avez pas besoin d’un formulaire pour le faire avec Prototype. Il suffit d'utiliser fonction 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'
5
Thibaut Barrère

Je ne suis pas tout à fait sûr moi-même, je me souviens d'avoir vu jQuery le faire dans une certaine mesure, mais il ne gère pas du tout les enregistrements hiérarchiques, et encore moins de manière amicale avec php.

Une chose que je sais avec certitude, est que lorsque vous créez des URL et que vous collez le produit dans le domaine principal, n'utilisez pas uniquement de la colle à chaînes pour le faire, sinon vous vous ouvrirez la porte à un coupe-page très pratique.

Par exemple, certains logiciels publicitaires insèrent dans la chaîne de version tout ce qui exécute votre flash. C’est bien quand sa chaîne adobes est générique, mais c’est cependant très naïf et explose dans un fouillis embarrassant pour les personnes qui ont installé Gnash, car la chaîne de la version gnash’es contient une licence complète de droits d’auteur sous GPL, avec URL et <a href> tags. En l'utilisant dans votre générateur d'annonceurs, vous obtenez une page qui s'ouvre et un code HTML déséquilibré s'affiche dans le domaine.

La morale de l'histoire:

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

Ne pas:

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

Google a besoin d'apprendre cette astuce. J'ai essayé de signaler le problème, ils semblent ne pas s'en soucier.

3
Kent Fredric

Comme le dit Stein, vous pouvez utiliser le prototype de bibliothèque javascript de http://www.prototypejs.org . Incluez le JS et c'est très simple alors, $('formName').serialize() retournera ce que vous voulez!

3
Shyam

Pour ceux d'entre nous qui préfèrent jQuery, vous devriez utiliser le plugin formulaire: http://plugins.jquery.com/project/form , qui contient une méthode formSerialize.

2
Cugel

Vous pouvez le faire de nos jours avec FormData et URLSearchParams sans avoir besoin de boucler sur quoi que ce soit.

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

Les anciens navigateurs auront besoin d'un polyfill, cependant.

1
Björn Tantau

Ces réponses sont très utiles, mais je veux ajouter une autre réponse, qui peut vous aider à créer une URL complète. Cela peut vous aider à concatter la base url, path, hash et parameters.

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

Vous pouvez télécharger via npm https://www.npmjs.com/package/build-url

Démo:

;(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);
1
Hien Nguyen
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>
1
Mahdi Bashirpour

C'est probablement trop tard pour répondre à votre question.
J'avais la même question et je n'aimais pas continuer à ajouter des chaînes pour créer une URL. Donc, j'ai commencé à utiliser $ .param comme techhouse expliqué.
J'ai également trouvé une bibliothèque RI.js qui crée facilement les URL pour vous. Plusieurs exemples vous aideront: Documentation URI.js .
Voici l'un d'entre eux:

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"]);`
0
SaraNa