Cara membuat string kueri dengan Javascript


Jawaban:


-24

Saya mencoba mencari jawaban untuk pertanyaan ini beberapa waktu yang lalu, tetapi saya akhirnya menulis fungsi saya sendiri yang mengekstrak nilai dari formulir ..

itu tidak sempurna tetapi sesuai dengan kebutuhan saya.

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 mengembalikan pemetaan (kunci -> nilai) parameter. input adalah elemen form (DOM Element)

Itu tidak menangani bidang yang memungkinkan banyak pilihan.


44
Apakah hanya saya atau ini tidak menjawab pertanyaan sama sekali? Dia meminta string kueri, bukan array yang dipetakan.
Jake Wilson

2
@ JakeWilson Ya, jawaban ini hanya setengah menjawab pertanyaan. Array masih perlu masuk ke format string kueri.
Hutch Moore

8
wow aku pasti noob di JS saat itu. Menggunakan new Array()untuk menginisialisasi kamus. Tetapi sekali lagi, kodenya terlihat jauh lebih bersih daripada beberapa omong kosong yang akan saya tulis hari ini!
hasen

2
@ telah mungkin Anda akan mempertimbangkan untuk mengedit jawaban ini, atau, um, well, hapus saja? Ini memiliki semakin banyak downvotes setiap kali saya gulir ke sana = -D (Saya bahkan ingat waktu ketika memiliki rasio positif ...)
Klesun

1
@ ArturKlesun ya, tidak. Saya tidak peduli Anda dapat mencoba bertanya kepada orang yang mengajukan pertanyaan untuk tidak menerima jawaban ini.
Hasen

220

Pembaruan 2k20: gunakan solusi Josh dengan URLSearchParams.toString () .

Jawaban lama:


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

Untuk browser yang tidak mendukung sintaks fungsi panah yang memerlukan ES5, ubah .map...baris menjadi

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

8
Solusi terbaik yang pernah saya lihat - sangat bersih dan ringkas. Namun, beberapa peringatan. 1) dalam .map (), k dan params [k] harus dikodekan, mis. EncodeURIComponent (k) dan encodeURIComponent (params [k]). 2) Anda diizinkan memiliki lebih dari satu instance parameter bernama dalam string kueri. Jika Anda menginginkan kemampuan itu, Anda harus menggunakan array alih-alih objek (sebagian besar aplikasi tidak menginginkan atau membutuhkannya).
John Deighan

9
3) Tidak semua browser akan mendukung sintaks fungsi panah (yang membutuhkan ES5). Jika Anda ingin mendukung semua browser (dan menyandikan bagian-bagiannya), ganti .map () dengan .map (fungsi (k) {return encodeURIComponent (k) + '=' + encodeURIComponent (params [k]);})
John Deighan

1
Cantik. Sangat cantik.
Mikko Ohtamaa

9
"jquery tidak cukup"
Eugene Pankov

1
@ user1738579 Saya mengedit jawaban untuk juga menyertakan contoh Anda untuk non-ES5.
Taylor Edmiston

134

Jika Anda menggunakan jQuery, Anda mungkin ingin memeriksa jQuery.param() http://api.jquery.com/jQuery.param/

Contoh:

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

13
Ini sebenarnya jawaban yang benar! String kueri untuk formulir adalah $.param($('#myform').serializeArray()).
Jesse

7
@Jesse, itu akan menjadi hasil yang sama dengan:$('#myform').serialize()
golok

94
jQuery !== JavaScript
gphilip

14
@ gphilip Nah itu sebabnya saya memulai respons dengan "Jika Anda menggunakan jQuery ...". Kalau tidak, jika Anda ingin mengimplementasikannya di vanilla JS Anda dapat memeriksa implementasi di jQuery.param()sini github.com/jquery/jquery/blob/master/src/serialize.js :)
Klemen Tušar

2
Tidak seperti jawaban saya yang satu ini mendukung objek bersarang sepertisomeStr=value1&someObj[a]=5&someObj[b]=6&someArr[]=1&someArr[]=2
Klesun

113

API URLSearchParams tersedia di semua browser modern. Sebagai contoh:

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


3
Jawaban terbaik di sini. Hanya untuk menambahkannya, Anda dapat melakukannya params.append(key, value)nanti untuk menambahkan params pencarian baru dalam skenario yang lebih rumit.
Mingwei Zhang

4
Perhatikan bahwa nilai tidak terdefinisi dan nol disertakan pada string terakhir:x=null&y=undefined
pomber

2
Juga, jika Anda sudah memiliki objek URL (misalnya const url = new URL("https://stackoverflow.com")), Anda dapat mengatur string kueri url.search = new URLSearchParams({foo: "bar"})atauurl.searchParams.append("foo", "bar")
Miguel Pynto

Perhatikan bahwa TS akan memperingatkan tentang penggunaan objek biasa, tetapi tetap berfungsi dengan baik
Vadorequest

@pomber Ada ide bagus untuk memfilter item yang tidak ditentukan itu?
Dan Gayle

53

Ini tidak langsung menjawab pertanyaan Anda, tetapi inilah fungsi umum yang akan membuat URL yang berisi parameter string kueri. Parameter (nama dan nilai) dengan aman diloloskan untuk dimasukkan dalam 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

1
Apakah ada fungsi bawaan yang mirip dengan ini di salah satu kerangka kerja javascript populars seperti jquery, mootools, dll ...?
Samuel

Solusi JavaScript asli yang lebih tangguh ada di stackoverflow.com/a/1714899/1269037
Dan Dascalescu

Implementasi paling aneh yang pernah ada, mengapa Anda perlu menginisialisasi new Arraysementara Anda benar-benar menggunakannya sebagai objek? o, O
Umut Sirin

@UmutSirin Lol ya saya tidak tahu banyak tentang Javascript pada saat itu. xD Saya pikir saya memperlakukannya seperti array PHP. Silakan refactor jika Anda mau.
Michael

@Michael Haha, ya. Saya baru saja mengirim suntingan. Terima kasih atas jawabannya!
Umut Sirin

22

Dengan jQuery Anda dapat melakukannya dengan $.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"

17

ES2017 (ES8)

Memanfaatkan Object.entries(), yang mengembalikan array [key, value]pasangan objek. Misalnya, untuk {a: 1, b: 2}itu akan kembali[['a', 1], ['b', 2]] . Itu tidak didukung (dan tidak akan) hanya oleh IE.

Kode:

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

Contoh:

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

Hasil:

"name=John&gender=male"


10

Tidak, saya tidak berpikir standar JavaScript sudah ada di dalamnya, tetapi Prototipe JS memiliki fungsi itu (tentunya sebagian besar kerangka kerja JS lainnya juga, tapi saya tidak tahu mereka), mereka menyebutnya serialisasi .

Saya dapat merekomendasikan Prototipe JS, ini berfungsi dengan sangat baik. Satu-satunya kelemahan saya benar-benar memperhatikan itu ukuran (beberapa ratus kb) dan ruang lingkup (banyak kode untuk ajax, dom, dll.). Jadi jika Anda hanya ingin bentuk serializer itu berlebihan, dan secara tegas jika Anda hanya ingin itu fungsi Ajax (yang terutama apa yang saya gunakan untuk itu) itu berlebihan. Kecuali jika Anda berhati-hati, Anda mungkin menemukan bahwa itu melakukan sedikit "sihir" (seperti memperluas setiap elemen dom yang disentuhnya dengan fungsi Prototipe JS hanya untuk menemukan elemen) membuatnya lambat pada kasus-kasus ekstrim.


Hanya ingin tahu apakah ada sesuatu yang built-in. Sepertinya harus ada. Saya benci prototipe, tapi saya tidak menentang Anda :)

Ketika JavaScript dirancang, Ajax belum ditemukan, karenanya menguraikan formulir hanya untuk mendapatkan querystring (yang akan dibuat sendiri saat dikirim) mungkin tidak masuk akal. Hari ini, sulit ... Btw, dibandingkan dengan script.aculo.us, prototipe itu bagus . :)
Stein G. Strindhaug

10

querystring dapat membantu.

Jadi kamu bisa

const querystring = require('querystring')

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

3
Untuk aplikasi frontend, Anda mungkin juga mempertimbangkan npmjs.com/package/qs
Robert Pankowecki

@RobertPankowecki, ya, qs lebih baik dan sudah ada di gudang senjata saya, tepuk tangan!
ImLeo

6

Jika Anda tidak ingin menggunakan pustaka, ini harus mencakup sebagian besar / semua jenis elemen formulir yang sama.

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

Terima kasih! Saya hanya menghadapi masalah yang sama dengan poster aslinya, dan fungsi Anda persis seperti yang saya butuhkan.
dagw

4

Anda sebenarnya tidak memerlukan formulir untuk melakukan ini dengan Prototipe. Cukup gunakan fungsi 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'

4
Memang, Anda menjawab hampir 10 tahun yang lalu, tetapi kode ini sekarang tidak digunakan lagi.
SEoF

4

Anda dapat melakukannya saat ini dengan FormDatadan URLSearchParamstanpa perlu mengulang apa pun.

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

Peramban yang lebih lama akan membutuhkan polyfill.


3

Saya sendiri tidak sepenuhnya yakin, saya ingat melihat jQuery melakukannya sampai batas tertentu, tetapi tidak menangani catatan hierarki sama sekali, apalagi dengan cara yang bersahabat dengan php.

Satu hal yang saya tahu pasti, adalah ketika membangun URL dan menempelkan produk ke dom, jangan hanya menggunakan string-lem untuk melakukannya, atau Anda akan membuka diri Anda ke pemecah halaman yang berguna.

Misalnya, perangkat lunak periklanan tertentu memasukkan string versi dari apa pun yang menjalankan flash Anda. Ini baik-baik saja ketika adobesnya menggunakan string sederhana yang umum, tetapi bagaimanapun, itu sangat naif, dan meledak dalam kekacauan yang memalukan bagi orang-orang yang telah menginstal Gnash, karena string versi gnash'es kebetulan berisi lisensi hak cipta GPL yang penuh sesak, lengkap dengan URL dan <a href> tag. Dengan menggunakan ini di generator pengiklan string-lem Anda, menghasilkan halaman membuka dan memiliki HTML yang tidak seimbang muncul di dom.

Moral cerita:

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

Tidak:

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

Google perlu mempelajari trik ini. Saya mencoba melaporkan masalah, mereka tampaknya tidak peduli.


Tepat. Document.write begitu tahun 1995.

2

Seperti kata Stein, Anda dapat menggunakan prototipe perpustakaan javascript dari http://www.prototypejs.org . Sertakan JS dan itu sangat sederhana, $('formName').serialize()akan mengembalikan apa yang Anda inginkan!



2

Mungkin sedikit berlebihan tetapi cara terbersih yang saya temukan yang didasarkan pada beberapa jawaban di sini:

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

Sumber


1

Jawaban ini sangat membantu, tetapi saya ingin menambahkan jawaban lain, yang dapat membantu Anda membangun URL lengkap. Hal ini dapat membantu Anda concat dasar url, path, hashdan parameters.

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

Anda dapat mengunduh melalui 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);


1

Saya tahu ini adalah jawaban yang sangat terlambat tetapi bekerja dengan sangat baik ...

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

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

catatan: object.entries akan mengembalikan kunci, nilai pasangan

output dari baris di atas adalah a = a & b = b

Semoga ini bisa membantu seseorang.

Selamat Coding ...


0

Apakah mungkin sudah terlambat untuk menjawab pertanyaan Anda.
Saya memiliki pertanyaan yang sama dan saya tidak suka terus menambahkan string untuk membuat URL. Jadi, saya mulai menggunakan $ .param seperti yang dijelaskan oleh techhouse .
Saya juga menemukan perpustakaan URI.js yang membuat URL dengan mudah untuk Anda. Ada beberapa contoh yang akan membantu Anda: URI.js Dokumentasi .
Ini salah satunya:

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

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>

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.