具有多个值的URLSearchParams



我从对象中创建了多个URLSearchParams,主要是因为它更易于编写和读取,但对于其中一些,我需要多个值为一个'变量';像这样:foo=bar&foo=baz.
现在我用.append来做,但是读起来很重,有多行非常相同。
是否有一种方法可以从构造函数中使用对象来实现?

let params;
// Currently used (and working) code
params = new URLSearchParams()
params.append("foo", "bar");
params.append("foo", "baz");
console.log(params.toString()); //Wanted result but heavy to read with more values
// Wanted code (but not the wanted result for now)
params = new URLSearchParams({
"foo": ["bar", "baz"]
});
console.log(params.toString());
params = new URLSearchParams({
"foo": "bar",
"foo": "baz"
});
console.log(params.toString());

URLSearchParams可以接受init值作为其构造函数的参数,包含以下内容:

之一:

  • 一个字符串,将从application/x-www-form-urlencoded格式解析。'?'开头字符将被忽略。

  • 名称-值字符串对的文字序列,或任何对象(如FormData对象),其迭代器产生的序列对字符串。注意,File条目将被序列化为[object File],而不是它们的文件名(就像在application/x-www-form-urlencoded形式).

  • 字符串键和字符串值的记录。

在你的情况下,第二种方法似乎效果最好,可以这样做:

const searchParams = new URLSearchParams([['foo', 'bar'],['foo', 'baz'],['foo', 'qux']])
console.log(searchParams.toString())


如果你想处理对象,你可以创建自己的结构,并使用一个函数来创建所需的数据

例如:

const params = [
{name: "foo", values: ["bar", "baz", "qux"]},
{name: "bar", values: ["foo", "foo2", "foo3"]},
]
const initParams = (params) => params.reduce((acc, curr) => {
const arr = curr.values.map(x => [curr.name, x])
return acc.concat(arr)
}, [])
const searchParams = new URLSearchParams(initParams(params))
console.log(searchParams.toString())

我将引入一个函数,从您想要的结构(包含字符串或字符串数组的对象)构建您需要的东西(URLSearchParams),推"heavy";详细信息在您自己的界面下方。一个简单的实现将只使用.append作为适当的:

// For TypeScript (e.g. Angular) users:
// function createSearchParams(params: { [key: string]: string | string[] }): URLSearchParams {
function createSearchParams(params) {
const searchParams = new URLSearchParams();
Object.entries(params).forEach(([key, values]) => {
if (Array.isArray(values)) {
values.forEach((value) => {
searchParams.append(key, value);
});
} else {
searchParams.append(key, values);
}
});
return searchParams;
}
console.log(createSearchParams({
foo: ["bar", "baz"],
hello: "world",
}).toString());

这提供了一个抽象,所以如果你决定在底层使用init方法,你可以这样做,例如:

function createSearchParams(params) {
return new URLSearchParams(Object.entries(params).flatMap(([key, values]) => Array.isArray(values) ? values.map((value) => [key, value]) : [[key, values]]));
}
console.log(createSearchParams({
foo: ["bar", "baz"],
hello: "world",
}).toString());

您的所有测试将继续通过,您不必更改消费代码。这比定义一个函数来将您想要的结构转换为URLSearchParams需要的要简洁得多,如RenaudC5的答案所示。

console.log('' + new URLSearchParams(['bar', 'baz', 'qux'].map(v=>['foo', v])))

首先使用parseParam函数处理数据

function parseParam(oldParams, newParams = {}, field = '') {
for (const key in oldParams) {
if (oldParams[key] !== null) {
let field3 = field.length > 0 ? field + '[' + key + ']' : key ;
switch (typeof oldParams[key]) {
case 'object':         
let object = parseParam(oldParams[key], newParams, field3);
newParams = Object.assign(newParams, object);  
break;
case 'string':
case 'number':                        
newParams[field3] = oldParams[key];
break;
}
}
}
return newParams;
}
let query = {
foo: ['bar', 'baz'],
status: 3,
products: {
door: [4, 8],
tile: 'not'
}
};
const urlParams = new URLSearchParams(parseParam(query));
console.log(urlParams.toString());
// foo[0]=bar&foo[1]=baz&status=3&products[door][0]=4&products[door][1]=8&products[tile]=not

您可以像这样创建多个参数

const params = new URLSearchParams({a:1,b:2,c:3});
console.log(params.toString());

或者你可以像这样给构造函数提供一个带有&的字符串new URLSearchParams("a=1&b=2&c=3")


当您将这些参数应用于url对象时,您可以使用url.search =覆盖所有参数。但是,如果url已经有一个参数,最好不要覆盖它,而是循环遍历新的UrlSearchParams对象,并使用url.searchParams.append

分别添加每个参数。

const params = new URLSearchParams("a=1&b=2&c=3");
console.log(params);
//You could apply them all to an url
const url = new URL("https://example.com");
url.search = params.toString();
console.log(url.toString())
//But if your url already contains a param, you gotta append new params separately
const url2 = new URL("https://example.com?x=1");
params.forEach((value, key) => { url2.searchParams.append(key, value); });
console.log(url2.toString())

最新更新