如何使用 Javascript 构建查询字符串
Posted
技术标签:
【中文标题】如何使用 Javascript 构建查询字符串【英文标题】:How to build query string with Javascript 【发布时间】:2010-09-23 22:13:11 【问题描述】:只是想知道 javascript 是否有任何内置的东西可以接受表单并返回查询参数,例如:"var1=value&var2=value2&arr[]=foo&arr[]=bar..."
多年来我一直在想这个问题。
【问题讨论】:
仅供参考:phpjs.org/functions/http_build_query Create query parameters in javascript的可能重复 【参考方案1】:The URLSearchParams API 在所有现代浏览器中都可用。例如:
const params = new URLSearchParams(
var1: "value",
var2: "value2",
arr: "foo",
);
console.log(params.toString());
//Prints "var1=value&var2=value2&arr=foo"
【讨论】:
这里是 imo 的最佳答案。只是为了添加它,您可以稍后在更复杂的场景中添加新的搜索参数params.append(key, value)
。
请注意,最终字符串中包含未定义和空值:x=null&y=undefined
另外,如果你已经有一个URL对象(例如const url = new URL("https://***.com")
),你可以设置它的查询字符串url.search = new URLSearchParams(foo: "bar")
或者url.searchParams.append("foo", "bar")
请注意,TS 会警告使用普通对象,但它仍然可以正常工作
@pomber 有什么好的想法可以过滤掉那些未定义的项目吗?【参考方案2】:
2k20 更新:将Josh's 解决方案与URLSearchParams.toString() 结合使用。
旧答案:
没有 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('&');
对于不支持需要 ES5 的箭头函数语法的浏览器,将 .map...
行更改为
.map(function(k) return esc(k) + '=' + esc(params[k]);)
【讨论】:
我见过的最好的解决方案 - 非常干净简洁。不过,有几点需要注意。 1) 在 .map() 中,k 和 params[k] 都应该被编码,例如encodeURIComponent(k) 和 encodeURIComponent(params[k])。 2) 查询字符串中允许有多个命名参数的实例。如果您想要该功能,则必须使用数组而不是对象(大多数应用程序不希望或不需要它)。 3) 并非所有浏览器都支持箭头函数语法(需要 ES5)。如果要支持所有浏览器(并对部分进行编码),请将上面的 .map() 替换为 .map(function(k) return encodeURIComponent(k) + '=' + encodeURIComponent(params[k]);) "没有足够的 jquery" 超级优雅紧凑。 @user1738579 我编辑了答案以包括您的非 ES5 示例。【参考方案3】:如果您使用 jQuery,您可能需要查看 jQuery.param()
http://api.jquery.com/jQuery.param/
例子:
var params =
parameter1: 'value1',
parameter2: 'value2',
parameter3: 'value3'
;
var query = $.param(params);
console.log(query);
这将打印出来:
parameter1=value1¶meter2=value2¶meter3=value3
【讨论】:
这其实是正确答案!表单的查询字符串是$.param($('#myform').serializeArray())
。
@Jesse,这将与以下结果相同:$('#myform').serialize()
jQuery !== JavaScript
@gphilip 这就是为什么我以“如果您使用 jQuery ...”开始回复。否则,如果您想在 vanilla JS 中实现它,您可以在此处检查 jQuery.param()
的实现 github.com/jquery/jquery/blob/master/src/serialize.js :)
与我的回答不同,这个支持嵌套对象,如someStr=value1&someObj[a]=5&someObj[b]=6&someArr[]=1&someArr[]=2
【参考方案4】:
这不会直接回答您的问题,但这是一个通用函数,它将创建一个包含查询字符串参数的 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
【讨论】:
在 jquery、mootools 等流行的 javascript 框架之一中是否有与此类似的内置功能...? 更强大的原生 JavaScript 解决方案位于 ***.com/a/1714899/1269037 有史以来最奇怪的实现,为什么在实际将new Array
用作对象时需要初始化它? o,o
@UmutSirin Lol 是的,当时我对 Javascript 知之甚少。 xD 我想我把它当作一个 PHP 数组来对待。如果需要,请随意重构。
@Michael 哈哈,是的。我刚刚发送了一个编辑。谢谢你的回答!【参考方案5】:
创建一个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());
输出将是
http://www.google.com/search?q=This+is+seach+query
【讨论】:
这是最佳答案【参考方案6】: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('&');
示例:
buildURLQuery(name: 'John', gender: 'male');
结果:
"name=John&gender=male"
【讨论】:
改用url.spec.whatwg.org/#urlsearchparams【参考方案7】:使用 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"
【讨论】:
【参考方案8】:querystring 可以帮忙。
所以,你可以
const querystring = require('querystring')
url += '?' + querystring.stringify(parameters)
【讨论】:
对于前端应用你也可以考虑npmjs.com/package/qs @RobertPankowecki,是的,qs 更好,并且已经在我的武器库中,干杯!【参考方案9】:不,我不认为标准 JavaScript 内置了该功能,但 Prototype JS 具有该功能(当然大多数其他 JS 框架也有,但我不知道它们),他们称之为serialize。
我可以推荐 Prototype JS,它工作得很好。我真正注意到的唯一缺点是它的大小(几百 kb)和范围(ajax、dom 等的大量代码)。因此,如果您只想要一个表单序列化程序,那就太过分了,严格来说,如果您只想要它的 Ajax 功能(这主要是我使用它的目的),那就太过分了。除非你很小心,否则你可能会发现它做了太多的“魔法”(比如使用 Prototype JS 函数扩展它接触到的每个 dom 元素只是为了找到元素)使其在极端情况下变慢。
【讨论】:
只是想知道是否有内置的东西。好像应该有。我讨厌原型,但我不反对你:) 在设计 JavaScript 时,还没有发现 Ajax,因此解析表单只是为了获取查询字符串(提交时它会自行创建)可能没有多大意义。今天确实如此,艰难...顺便说一句,与 script.aculo.us 相比,原型 nice。 :)【参考方案10】:如果您不想使用库,这应该涵盖大多数/所有相同的表单元素类型。
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('&');
【讨论】:
谢谢!我刚刚面临与原始海报相同的问题,而您的功能正是我所需要的。【参考方案11】:您现在可以使用 FormData
和 URLSearchParams
做到这一点,而无需循环任何内容。
const formData = new FormData(form);
const searchParams = new URLSearchParams(formData);
const queryString = searchParams.toString();
不过,较旧的浏览器需要 polyfill。
【讨论】:
【参考方案12】:可能有点多余,但我发现的最简洁的方法是建立在此处的一些答案之上的:
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,
)
Source
【讨论】:
【参考方案13】:我自己并不完全确定,我记得曾在一定程度上看到过 jQuery,但它根本不处理分层记录,更不用说以 php 友好的方式了。
我确实知道的一件事是,在构建 URL 并将产品粘贴到 dom 中时,不要只使用字符串胶水来执行此操作,否则您将自己打开一个方便的分页器。
例如,某些广告软件会从运行您的闪存的任何程序中嵌入版本字符串。当它的 adobes 通用简单字符串时这很好,但是,这非常幼稚,并且对于安装了 Gnash 的人来说会陷入尴尬的混乱,因为 gnash 的版本字符串恰好包含完整的 GPL 版权许可,并带有 URL和 标签。在您的字符串胶水广告客户生成器中使用它会导致页面打开并且在 dom 中出现不平衡的 html。
故事的寓意:
var foo = document.createElement("elementnamehere");
foo.attribute = allUserSpecifiedDataConsideredDangerousHere;
somenode.appendChild(foo);
不是:
document.write("<elementnamehere attribute=\""
+ ilovebrokenwebsites
+ "\">"
+ stringdata
+ "</elementnamehere>");
Google 需要学习这个技巧。我试图报告这个问题,他们似乎不在乎。
【讨论】:
正确。 Document.write 是所以 1995,无论如何。【参考方案14】:您实际上并不需要一个表单来使用 Prototype 执行此操作。只需使用Object.toQueryString function:
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'
【讨论】:
当然,您在近 10 年前就回答了,但现在已弃用此代码。【参考方案15】:正如 Stein 所说,您可以使用来自 http://www.prototypejs.org 的原型 javascript 库。
包含 JS 就很简单了,$('formName').serialize()
会返回你想要的!
【讨论】:
【参考方案16】:对于我们这些喜欢 jQuery 的人,您可以使用表单插件:http://plugins.jquery.com/project/form,其中包含一个 formSerialize 方法。
【讨论】:
【参考方案17】:我知道这是很晚的答案,但效果很好......
var obj =
a:"a",
b:"b"
Object.entries(obj).map(([key, val])=>`$key=$val`).join("&");
注意:object.entries 将返回键值对
上面一行的输出将是 a=a&b=b
希望它对某人有所帮助。
快乐编码...
【讨论】:
【参考方案18】:现在回答您的问题可能为时已晚。 我有同样的问题,我不想继续附加字符串来创建 URL。所以,我开始使用 $.param 作为techhouse 解释。 我还找到了一个URI.js 库,可以轻松地为您创建 URL。有几个示例可以帮助您:URI.js Documentation。 这是其中之一:
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"]);`
【讨论】:
【参考方案19】:这些答案非常有帮助,但我想添加另一个答案,它可以帮助您构建完整的 URL。
这可以帮助您连接基础 url
、path
、hash
和 parameters
。
var url = buildUrl('http://mywebsite.com',
path: 'about',
hash: 'contact',
queryParams:
'var1': 'value',
'var2': 'value2',
'arr[]' : 'foo'
);
console.log(url);
您可以通过npm下载https://www.npmjs.com/package/build-url
演示:
;(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);
【讨论】:
【参考方案20】: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>
【讨论】:
【参考方案21】:UrlSearchParams
API 是一个很好的建议,但我不敢相信没有人提到非常有用的 .get
和 .set
方法。它们可用于操作查询字符串,不仅非常易于使用,而且还解决了您可能遇到的许多问题。例如,就我而言,我想构建一个没有重复键的查询字符串。 .set
为您解决了这个问题。引用自MDN docs:
URLSearchParams.set() 将与给定搜索参数关联的值设置为给定值。如果有多个值,则删除其他值。
示例 (from 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"
替代的,更短的语法:
let url = new URL('https://example.com?foo=1&bar=2');
// Add a third parameter.
url.searchParams.set('baz', 3);
params.toString(); // "foo=1&bar=2&baz=3"
【讨论】:
以上是关于如何使用 Javascript 构建查询字符串的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 javascript 从 Web 服务返回的二进制字符串构建 PDF 文件