So erstellen Sie eine Abfragezeichenfolge mit Javascript

167

Ich frage mich nur, ob in Javascript etwas integriert ist, das ein Formular annehmen und die Abfrageparameter zurückgeben kann, z. "var1=value&var2=value2&arr[]=foo&arr[]=bar..."

Ich habe mich das seit Jahren gefragt.

Liam
quelle
1
Zu Ihrer
1
Mögliches Duplikat von Abfrageparameter in Javascript erstellen
Nerdroid

Antworten:

-24

Ich habe vor einiger Zeit versucht, nach einer Antwort auf diese Frage zu suchen, aber am Ende habe ich meine eigene Funktion geschrieben, die die Werte aus dem Formular extrahiert.

Es ist nicht perfekt, aber es passt zu meinen Bedürfnissen.

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 gibt eine (Schlüssel -> Wert) Zuordnung der Parameter zurück. Die Eingabe ist das Formularelement (DOM-Element).

Es werden keine Felder verarbeitet, die eine Mehrfachauswahl ermöglichen.

hasen
quelle
44
Ist es nur ich oder beantwortet dies die Frage überhaupt nicht? Er fragte nach einer Abfragezeichenfolge, nicht nach einem zugeordneten Array.
Jake Wilson
2
@ JakeWilson Ja, diese Antwort beantwortet nur die Hälfte der Frage. Das Array muss noch in ein Abfragezeichenfolgenformat gebracht werden.
Hutch Moore
8
Wow, ich muss damals ein Noob bei JS gewesen sein. Verwenden Sie new Array(), um ein Wörterbuch zu initialisieren. Aber andererseits sieht der Code viel sauberer aus als der Mist, den ich heutzutage schreiben würde!
hasen
2
@hasen Vielleicht würden Sie erwägen, diese Antwort zu bearbeiten oder sie zu löschen? Es hat jedes Mal mehr Downvotes, wenn ich dorthin scrolle = -D (ich erinnere mich sogar an die Zeit, als es ein positives Verhältnis hatte ...)
Klesun
1
@ ArturKlesun ja, nein. Es ist mir egal. Sie können versuchen, die Person, die die Frage gestellt hat, zu bitten, diese Antwort nicht zu akzeptieren.
Hasen
220

2k20-Update: Verwenden Sie Joshs Lösung mit URLSearchParams.toString () .

Alte Antwort:


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

Ändern Sie für Browser, die keine Pfeilfunktionssyntax unterstützen, für die ES5 erforderlich ist, die .map...Zeile in

    .map(function(k) {return esc(k) + '=' + esc(params[k]);})
Klesun
quelle
8
Beste Lösung, die ich bisher gesehen habe - sehr sauber und prägnant. Ein paar Vorbehalte. 1) In der .map () sollten sowohl k als auch params [k] codiert werden, z. B. encodeURIComponent (k) und encodeURIComponent (params [k]). 2) Sie dürfen mehr als eine Instanz eines benannten Parameters in einer Abfragezeichenfolge haben. Wenn Sie diese Funktion wünschen, müssen Sie ein Array anstelle eines Objekts verwenden (die meisten Anwendungen möchten oder benötigen dies nicht).
John Deighan
9
3) Nicht alle Browser unterstützen die Pfeilfunktionssyntax (für die ES5 erforderlich ist). Wenn Sie alle Browser unterstützen möchten (und die Teile codieren möchten), ersetzen Sie die obige .map () durch .map (Funktion (k) {return encodeURIComponent (k) + '=' + encodeURIComponent (params [k]);})
John Deighan
1
Wunderschönen. Wahrhaft schön.
Mikko Ohtamaa
9
"nicht genug jquery"
Eugene Pankov
1
@ user1738579 Ich habe die Antwort so bearbeitet, dass sie auch Ihr Beispiel für Nicht-ES5 enthält.
Taylor Edmiston
134

Wenn Sie jQuery verwenden, sollten Sie http://api.jquery.com/jQuery.param/ überprüfen.jQuery.param()

Beispiel:

var params = {
    parameter1: 'value1',
    parameter2: 'value2',
    parameter3: 'value3' 
};
var query = $.param(params);
document.write(query);
Klemen Tušar
quelle
13
Das ist eigentlich die richtige Antwort! Die Abfragezeichenfolge für ein Formular lautet $.param($('#myform').serializeArray()).
Jesse
7
@ Jesse, das wäre das gleiche Ergebnis wie:$('#myform').serialize()
Hackbeil
94
jQuery !== JavaScript
Gphilip
14
@gphilip Deshalb habe ich die Antwort mit "Wenn Sie jQuery verwenden ..." gestartet. Andernfalls, wenn Sie es in Vanilla JS implementieren möchten, können Sie die Implementierung von jQuery.param()hier github.com/jquery/jquery/blob/master/src/serialize.js :)
Klemen Tušar
2
Im Gegensatz zu meiner Antwort unterstützt diese verschachtelte Objekte wiesomeStr=value1&someObj[a]=5&someObj[b]=6&someArr[]=1&someArr[]=2
Klesun
112

Die URLSearchParams-API ist in allen modernen Browsern verfügbar. Beispielsweise:

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

Josh
quelle
3
Beste Antwort hier imo. params.append(key, value)Um dies zu ergänzen, können Sie später in komplizierteren Szenarien neue Suchparameter hinzufügen.
Mingwei Zhang
4
Beachten Sie, dass undefinierte und Nullwerte in der letzten Zeichenfolge enthalten sind:x=null&y=undefined
pomber
2
Wenn Sie beispielsweise bereits ein URL-Objekt haben const url = new URL("https://stackoverflow.com"), können Sie dessen url.search = new URLSearchParams({foo: "bar"})url.searchParams.append("foo", "bar")
Abfragezeichenfolgen festlegen
Beachten Sie, dass TS vor der Verwendung eines einfachen Objekts warnt, aber dennoch
einwandfrei
@pomber Irgendwelche guten Ideen zum Herausfiltern dieser undefinierten Elemente?
Dan Gayle vor
53

Dies beantwortet Ihre Frage nicht direkt, aber hier ist eine generische Funktion, die eine URL erstellt, die Abfragezeichenfolgenparameter enthält. Die Parameter (Namen und Werte) werden zur Aufnahme in eine URL sicher maskiert.

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
quelle
1
Gibt es eine ähnliche integrierte Funktion wie diese in einem der beliebtesten Javascript-Frameworks wie JQuery, Mootools usw.?
Samuel
Eine robustere native JavaScript-Lösung finden Sie unter stackoverflow.com/a/1714899/1269037
Dan Dascalescu,
Die seltsamste Implementierung aller Zeiten. Warum müssen Sie eine new ArrayWeile initialisieren, während Sie sie tatsächlich als Objekt verwenden? o, O
Umut Sirin
@UmutSirin Lol Ja, ich wusste damals nicht viel über Javascript. xD Ich glaube, ich habe es wie ein PHP-Array behandelt. Fühlen Sie sich frei zu refactor, wenn Sie wollen.
Michael
@ Michael Haha, ja. Ich habe gerade eine Bearbeitung gesendet. Danke für die Antwort!
Umut Sirin
22

Mit jQuery können Sie dies tun, indem Sie $.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
quelle
17

ES2017 (ES8)

Verwenden von Object.entries(), wodurch ein Array von Objektpaaren zurückgegeben [key, value]wird. Zum Beispiel {a: 1, b: 2}würde es zurückkehren [['a', 1], ['b', 2]]. Es wird nicht nur vom IE unterstützt (und wird es auch nicht sein).

Code:

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

Beispiel:

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

Ergebnis:

"name=John&gender=male"
Przemek
quelle
Verwenden Sie stattdessen url.spec.whatwg.org/#urlsearchparams
Boris
10

Nein, ich glaube nicht, dass Standard-JavaScript das eingebaut hat, aber Prototype JS hat diese Funktion (sicherlich haben die meisten anderen JS-Frameworks auch, aber ich kenne sie nicht), sie nennen es serialisieren .

Ich kann Prototype JS empfehlen, es funktioniert ganz gut. Der einzige Nachteil, den ich wirklich bemerkt habe, ist die Größe (einige hundert KB) und der Umfang (viel Code für Ajax, Dom usw.). Wenn Sie also nur einen Formularserialisierer möchten, ist dieser übertrieben, und genau genommen, wenn Sie nur die Ajax-Funktionalität wünschen (für die ich ihn hauptsächlich verwendet habe), ist er übertrieben. Wenn Sie nicht vorsichtig sind, werden Sie möglicherweise feststellen, dass es etwas zu viel "Magie" bewirkt (wie das Erweitern jedes dom-Elements, das es berührt, mit Prototype JS-Funktionen, nur um Elemente zu finden), was es in extremen Fällen langsam macht.

Stein G. Strindhaug
quelle
Ich frage mich nur, ob etwas eingebaut ist. Scheint so zu sein. Ich hasse Prototypen, aber ich halte das nicht gegen dich :)
Als JavaScript entworfen wurde, wurde Ajax noch nicht entdeckt. Daher war es wahrscheinlich nicht sinnvoll, ein Formular zu analysieren, um den Querystring zu erhalten (den es beim Senden selbst erstellen würde). Heute ist es schwierig ... Übrigens ist der Prototyp im Vergleich zu script.aculo.us nett . :)
Stein G. Strindhaug
10

Querystring kann helfen.

Also kannst du

const querystring = require('querystring')

url += '?' + querystring.stringify(parameters)
ImLeo
quelle
3
Für Frontend-Anwendungen können Sie auch npmjs.com/package/qs
Robert Pankowecki
@ RobertPankowecki, ja, qs ist besser und schon in meinem Arsenal, Prost!
ImLeo
6

Wenn Sie keine Bibliothek verwenden möchten, sollte dies die meisten / alle gleichen Formularelementtypen abdecken.

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
quelle
Vielen Dank! Ich hatte gerade das gleiche Problem wie das Originalplakat, und Ihre Funktion war genau das, was ich brauchte.
Tag
4

Sie benötigen dazu kein Formular für Prototype. Verwenden Sie einfach die Object.toQueryString-Funktion :

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
quelle
4
Zugegeben, Sie haben vor fast 10 Jahren geantwortet, aber dieser Code ist jetzt veraltet.
SEoF
4

Sie können dies heutzutage mit FormDataund URLSearchParamsohne die Notwendigkeit tun, irgendetwas zu durchlaufen.

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

Ältere Browser benötigen jedoch eine Polyfüllung.

Björn Tantau
quelle
3

Ich bin mir selbst nicht ganz sicher, ich erinnere mich, dass jQuery dies bis zu einem gewissen Grad getan hat, aber es verarbeitet überhaupt keine hierarchischen Datensätze, geschweige denn auf PHP-freundliche Weise.

Eine Sache, die ich mit Sicherheit weiß, ist, dass Sie beim Erstellen von URLs und beim Einfügen des Produkts in den Dom nicht nur String-Kleber verwenden, da Sie sich sonst einem praktischen Seitenumbruch öffnen.

Zum Beispiel integriert bestimmte Werbesoftware die Versionszeichenfolge von dem, auf dem Ihr Flash ausgeführt wird. Dies ist in Ordnung, wenn es sich um eine generische einfache Zeichenfolge handelt, die jedoch sehr naiv ist und für Leute, die Gnash installiert haben, in einem peinlichen Durcheinander explodiert, da die Versionszeichenfolge von gnash zufällig eine vollständige GPL-Copyright-Lizenz mit URLs enthält und <a href> -Tags. Wenn Sie dies in Ihrem String-Glue-Advertiser-Generator verwenden, wird die Seite aufgeblasen und im Dom wird unausgeglichenes HTML angezeigt.

Die Moral der Geschichte:

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

Nicht:

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

Google muss diesen Trick lernen. Ich habe versucht, das Problem zu melden, sie scheinen sich nicht darum zu kümmern.

Kent Fredric
quelle
Direkt am. Document.write ist sowieso so 1995.
2

Wie Stein sagt, können Sie die Prototyp-Javascript-Bibliothek von http://www.prototypejs.org verwenden . Fügen Sie die JS hinzu und es ist dann sehr einfach, $('formName').serialize()wird zurückgeben, was Sie wollen!

Shyam
quelle
2

Könnte ein bisschen überflüssig sein, aber der sauberste Weg, den ich gefunden habe, baut auf einigen der Antworten hier auf:

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

Quelle

David Pascoal
quelle
1

Diese Antworten sind sehr hilfreich, aber ich möchte eine weitere Antwort hinzufügen, die Ihnen beim Erstellen einer vollständigen URL helfen kann. Dies kann Ihnen concat Basis helfen url, path, hashund parameters.

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

Sie können über npm https://www.npmjs.com/package/build-url herunterladen

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
quelle
1

Ich weiß, dass dies eine sehr späte Antwort ist, aber sehr gut funktioniert ...

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

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

Hinweis: object.entries gibt Schlüssel- und Wertepaare zurück

Die Ausgabe von der obigen Zeile ist a = a & b = b

Hoffe es hilft jemandem.

Viel Spaß beim Codieren ...

ajaykumar mp
quelle
0

Es ist wahrscheinlich zu spät, um Ihre Frage zu beantworten.
Ich hatte die gleiche Frage und wollte nicht immer wieder Zeichenfolgen anhängen, um eine URL zu erstellen. Also fing ich an, $ .param zu verwenden, wie Techhouse erklärte.
Ich habe auch eine URI.js- Bibliothek gefunden, die die URLs einfach für Sie erstellt. Es gibt mehrere Beispiele, die Ihnen helfen werden: URI.js Dokumentation .
Hier ist einer von ihnen:

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
quelle
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
quelle