如何使用Javascript构建查询字符串

135 javascript forms string get

只是想知道是否有任何内置的Javascript可以获取一个Form并返回查询参数,例如:"var1 = value&var2 = value2&arr [] = foo&arr [] = bar ..."

多年来我一直在想这个.

Art*_*sun 192

没有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('&');
Run Code Online (Sandbox Code Playgroud)

对于不支持需要ES5的箭头函数语法的浏览器,请将.map...行更改为

    .map(function(k) {return esc(k) + '=' + esc(params[k]);})
Run Code Online (Sandbox Code Playgroud)

  • 3)并非所有浏览器都支持箭头函数语法(需要ES5).如果你想支持所有的浏览器(并对部件进行编码),用.map替换上面的.map()(函数(k){return encodeURIComponent(k)+'='+ encodeURIComponent(params [k]);}) (9认同)
  • 我见过的最佳解决方案 - 非常简洁明了.但有几点需要注意.1)在.map()中,k和params [k]都应该被编码,例如encodeURIComponent(k)和encodeURIComponent(params [k]).2)您可以在查询字符串中拥有多个命名参数实例.如果您需要该功能,则必须使用数组而不是对象(大多数应用程序不需要或不需要). (8认同)
  • "不够jquery" (7认同)

tec*_*use 132

如果您正在使用jQuery,可能需要查看jQuery.param() http://api.jquery.com/jQuery.param/

例:

var params = {
    parameter1: 'value1',
    parameter2: 'value2',
    parameter3: 'value3' 
};
?var query = $.param(params);
document.write(query);
Run Code Online (Sandbox Code Playgroud)

  • `jQuery!== JavaScript` (90认同)
  • @gphilip这就是为什么我用"如果你正在使用jQuery ......"开始响应的原因.否则,如果你想在vanilla JS中实现它,你可以检查`jQuery.param()`的实现,这里https://github.com/jquery/jquery/blob/master/src/serialize.js :) (13认同)
  • 这实际上是正确的答案!表单的查询字符串是`$ .param($('#myform').serializeArray())`. (12认同)
  • @Jesse,结果如下:`$('#myform').serialize()` (7认同)
  • 与我的答案不同,此代码支持嵌套对象,例如someStr = value1&someObj [a] = 5&someObj [b] = 6&someArr [] = 1&someArr [] = 2”。 (2认同)

Mic*_*ael 56

这不会直接回答您的问题,但这是一个通用函数,它将创建一个包含查询字符串参数的URL.安全地转义参数(名称和值)以包含在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
Run Code Online (Sandbox Code Playgroud)


小智 35

现在有用于此的API,特别是URLSearchParams API.给出的例子:

const params = new URLSearchParams({
  var1: "value",
  var2: "value2",
  arr: "foo",
});
console.log(params.toString());
Run Code Online (Sandbox Code Playgroud)

注意:最近与Chrome和Firefox 非常兼容,但如果您需要使用Microsoft和Apple浏览器,请务必小心,因为兼容性是部分的.

  • 看来你可以直接做`new URLSearchParams({var1:"value",var2:"value2"...}).toString()`nowadays https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams#语法 (9认同)
  • 最佳答案在这里。只是为了添加它,您可以稍后执行“params.append(key, value)”,以便在更复杂的场景中添加新的搜索参数。 (8认同)
  • 请注意,最终字符串中包含未定义和空值:`x=null&y=undefined` (8认同)
  • 另外,如果您已经有一个 URL 对象(例如 `const url = new URL("https://stackoverflow.com")`),您可以设置其查询字符串 `url.search = new URLSearchParams({foo: " bar"})` 或 `url.searchParams.append("foo", "bar")` (5认同)
  • 请注意,TS 会警告使用普通对象,但它仍然可以正常工作 (2认同)
  • 请注意,它对实体的编码与“encodeURIComponent()”不同:此处的空格被编码为“+”而不是“%20”。不确定这是否是某些服务出现问题的原因。 (2认同)

man*_*h_s 21

使用jQuery,你可以做到这一点 $.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"
Run Code Online (Sandbox Code Playgroud)


Tin*_*sae 18

创建一个 URL 对象并将值附加到 seachParameters

let stringUrl = "http://www.google.com/search";
let url = new URL(stringUrl);
let params = url.searchParams;
    params.append("q","This is seach query");

console.log( url.toString() );
Run Code Online (Sandbox Code Playgroud)

输出将是

http://www.google.com/search?q=This+is+seach+query
Run Code Online (Sandbox Code Playgroud)

  • 这是最佳答案 (2认同)

Prz*_*mek 14

ES2017(ES8)

利用Object.entries(),返回一个对象数组[key, value]对.例如,因为{a: 1, b: 2}它会返回[['a', 1], ['b', 2]].它不受IE支持(也不会支持).

码:

const buildURLQuery = obj =>
      Object.entries(obj)
            .map(pair => pair.map(encodeURIComponent).join('='))
            .join('&');
Run Code Online (Sandbox Code Playgroud)

例:

buildURLQuery({name: 'John', gender: 'male'});
Run Code Online (Sandbox Code Playgroud)

结果:

"name=John&gender=male"
Run Code Online (Sandbox Code Playgroud)

  • 使用 https://url.spec.whatwg.org/#urlsearchparams 代替 (2认同)

Ste*_*aug 10

不,我不认为标准JavaScript有内置,但Prototype JS有这个功能(当然大多数其他JS框架也有,但我不知道),他们称之为序列化.

我可以推荐Prototype JS,它工作得很好.唯一的缺点我真的注意到它的大小(几百kb)和范围(很多代码为ajax,dom等).因此,如果你只想要一个表单序列化器,那就太过分了,而且严格来说,如果你只想要它的Ajax功能(主要是我用它),那就太过分了.除非你小心,否则你可能会发现它有点过分"神奇"(比如扩展它与Prototype JS函数接触的每个dom元素只是为了找到元素),这使得它在极端情况下变慢.


ImL*_*Leo 7

查询串可以帮助.

所以你可以

const querystring = require('querystring')

url += '?' + querystring.stringify(parameters)
Run Code Online (Sandbox Code Playgroud)

  • 对于前端应用程序,您还可以考虑使用https://www.npmjs.com/package/qs (2认同)

Jon*_*ski 6

如果您不想使用库,则应该涵盖大多数/所有相同的表单元素类型.

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('&');
}
Run Code Online (Sandbox Code Playgroud)


Thi*_*ère 5

您实际上并不需要使用Prototype执行此操作的表单.只需使用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'
Run Code Online (Sandbox Code Playgroud)

  • 当然,您已经回答了将近10年前,但是现在不推荐使用此代码。 (2认同)

Bjö*_*tau 5

现在你可以做到这一点,FormData无论URLSearchParams是否需要循环任何东西。

const formData = new FormData(form);
const searchParams = new URLSearchParams(formData);
const queryString = searchParams.toString();
Run Code Online (Sandbox Code Playgroud)

不过,较旧的浏览器将需要一个polyfill。


Dav*_*oal 5

可能有点多余,但我发现的最干净的方法是基于这里的一些答案:

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,
})
Run Code Online (Sandbox Code Playgroud)

来源


Sim*_*one 5

APIUrlSearchParams是一个很好的建议,但我不敢相信没有人提到它的非常有用.get.set方法。它们可用于操作查询字符串,不仅非常易于使用,还可以解决您可能遇到的许多问题。例如,就我而言,我想构建一个没有重复键的查询字符串。.set为您解决这个问题。引用MDN 文档

URLSearchParams.set() 将与给定搜索参数关联的值设置为给定值。如果有多个值,则删除其他值。

示例(来自 MDN):

let url = new URL('https://example.com?foo=1&bar=2');
let params = new URLSearchParams(url.search);

// Add a third parameter
params.set('baz', 3);

params.toString(); // "foo=1&bar=2&baz=3"
Run Code Online (Sandbox Code Playgroud)

另一种更短的语法:

let url = new URL('https://example.com?foo=1&bar=2');

// Add a third parameter
url.searchParams.set('baz', 3);

url.searchParams.toString(); // "foo=1&bar=2&baz=3"
Run Code Online (Sandbox Code Playgroud)


Ken*_*ric 3

我自己也不太确定,我记得看到 jQuery 在一定程度上做到了这一点,但它根本不处理分层记录,更不用说以 php 友好的方式了。

我确实知道的一件事是,当构建 URL 并将产品粘贴到 dom 中时,不要只使用 string-glue 来完成此操作,否则您将面临一个方便的分页器。

例如,某些广告软件会内嵌运行 Flash 的版本字符串。当它是 adobes 通用简单字符串时,这很好,但是,这非常天真,并且对于安装了 Gnash 的人来说会陷入尴尬的混乱,因为 gnash'es 版本字符串恰好包含完整的 GPL 版权许可证,并带有 URL和 <a href> 标签。在你的字符串粘合广告生成器中使用它,会导致页面打开并在 dom 中出现不平衡的 HTML。

这个故事的主旨:

   var foo = document.createElement("elementnamehere"); 
   foo.attribute = allUserSpecifiedDataConsideredDangerousHere; 
   somenode.appendChild(foo); 
Run Code Online (Sandbox Code Playgroud)

不是:

   document.write("<elementnamehere attribute=\"" 
        + ilovebrokenwebsites 
        + "\">" 
        + stringdata 
        + "</elementnamehere>");
Run Code Online (Sandbox Code Playgroud)

谷歌需要学习这个技巧。我试图报告这个问题,他们似乎并不关心。