常见场景
传递 URL
参数是页面A与页面B通信时常用的方法。如:页面A是新闻列表页面,在点击某一条新闻的时候,需要带着新闻 ID
打开页面B新闻详情页面 pageB?id=${id}
,这样页面B就能根据解析 URL
上的 ID
获取具体的新闻详情了。
常见的格式化和解析方法
🔥🔥🔥 推荐一个好用的解析工具:Prettier URL
给出一段参数:
const query = {
a: 'a',
b: 1,
c:[1,2,3,{ cc: 'my_cc'}],
d: {
name:'name',
value: { num: 1}
},
e: "https://www.baidu.com?a=1&b=1#tag"
}
使用现有的库
先抛出结论:推荐使用 qs
query-string
地址:https://www.npmjs.com/package/query-string
stringify
import queryString from 'query-string';
console.log(queryString.stringify(query));
结果(c=1&c=2&c=3):a=a&a%3F.b=a_b&b=1&c=1&c=2&c=3&c=%5Bobject%20Object%5D&d=%5Bobject%20Object%5D&e=https%3A%2F%2Fwww.baidu.com%3Fa%3D1%26b%3D1%23tag
使用 comma 格式 stringify
import queryString from 'query-string';
console.log(queryString.stringify(query),{arrayFormat: 'comma'});
结果(c=1,2,3):a=a&a%3F.b=a_b&b=1&c=1,2,3,%5Bobject%20Object%5D&d=%5Bobject%20Object%5D&e=https%3A%2F%2Fwww.baidu.com%3Fa%3D1%26b%3D1%23tag
parse
解析:
import queryString from 'query-string';
const str = queryString.stringify(query),{arrayFormat: 'comma'})
queryString.parse(`?${str}`)
返回:
{
a: "a",
b: "1",
c:[ "1","2","3",[object Object]"],
d: "[object Object]",
e: "https://www.baidu.com?a=1&b=1#tag"
}
总结
- 不需要手动去掉
location.search
的?
- 数组处理支持
arrayFormat
:'bracket' | 'index' | 'comma'
- 具备
encodeURIComponent(key)
- 具备
encodeURIComponent(value)
- 无法处理 value 为对象的情况( 被处理成
'[object Object]'
),stringify + parse
后 这种值会丢失 - 重复的 key 的解析 ?a=1&a=a
{ a: ["1","a"]}
querystring
已经被废弃了,不要再使用了,这里直接给出结论
- 需要手动去掉
location.search
的?
- 数组处理支持
arrayFormat
:'bracket' | 'index' | 'comma'
- 具备
encodeURIComponent(key)
- 具备
encodeURIComponent(value)
- 无法处理 value 为对象的情况( 被处理成
'[object Object]'
),stringify + parse
后 这种值会丢失 - 重复的 key 的解析 ?a=1&a=a
{ a: ["1","a"]}
- 重复的 key 的解析 ?a=1&a=a
qs 【推荐】
github: https://github.com/ljharb/qs
stringify
import qs from 'qs';
console.log(qs.stringify(query));
结果:a=a&b=1&c%5B0%5D=1&c%5B1%5D=2&c%5B2%5D=3&c%5B3%5D%5Bcc%5D=my_cc&d%5Bname%5D=name&d%5Bvalue%5D%5Bnum%5D=1&e=https%3A%2F%2Fwww.baidu.com%3Fa%3D1%26b%3D1%23tag&a%3F.b=a_b
parse
解析:
import queryString from 'query-string';
const str = queryString.stringify(query),{arrayFormat: 'comma'})
queryString.parse(`?${str}`)
结果:
{
a: "a"
b: "1"
c: ["1","2",{ cc: "my_cc"}]
d: { name:"name", value:{} num: "1"}}
e: "https://www.baidu.com?a=1&b=1#tag"
}
总结
- 需要手动去掉
location.search
的?
- 数组处理支持
arrayFormat
:'indices' | 'bracket' | 'repeat' | 'comma'
- 具备
encodeURIComponent(key)
- 具备
encodeURIComponent(value)
- 可以处理 value 为对象的情况
- 重复的 key 的解析 ?a=1&a=a
{ a: ["1","a"]}
自己实现格式化和解析(仅限于 value 是基本类型)
抛出结论:
- 需要手动去掉
location.search
的?
- 具备
encodeURIComponent(key)
- 具备
encodeURIComponent(value)
- 无法处理 value 为对象的情况( 被处理成
'[object Object]'
)
方法一: split + reduce
格式化
const stringify = (query) => {
return Object.keys(query).reduce((pre,key) => {
return pre + `${encodeURIComponent(key)}=${encodeURIComponent(query[key])}&`
},'').slice(0,-1)
}
调用:console.log(stringify(query))
返回 :a=a&b=1&c=1%2C2%2C3%2C%5Bobject%20Object%5D&d=%5Bobject%20Object%5D&e=https%3A%2F%2Fwww.baidu.com%3Fa%3D1%26b%3D1%23tag
解析
const parse = (queryStr) => {
const str = queryStr.replace(/^\?/,'')
return queryStr.split('&').reduce((pre,key) => {
const [k,v] = key.split('=')
pre[decodeURIComponent(k)] = decodeURIComponent(v)
return pre
},{})
}
调用上面 stringigy
:parse(str)
返回:
{ a: 'a',
b: '1',
c: '1,2,3,[object Object]',
d: '[object Object]',
e: 'https://www.baidu.com?a=1&b=1#tag'
}
方法二 URL + URLSearchParams
URL: https://developer.mozilla.org/zh-CN/docs/Web/API/URL
URLSearchParams:https://developer.mozilla.org/zh-CN/docs/Web/API/URLSearchPar...
格式化
const url = new URL("https://example.com/?a=hello&b=world");
console.log(url.href);
// https://example.com/?a=hello&b=world
console.log(url.origin);
// https://example.com
const add_params = {
c: "a",
d: new String(2),
e: false.toString(),
};
const new_params = new URLSearchParams([
...Array.from(url.searchParams.entries()), // [["a","hello"],["b","world"]]
...Object.entries(add_params), // [["c","a"],["d","2"],["e","false"]]
]).toString();
console.log(new_params);
// a=hello&b=world&c=a&d=2&e=false
const new_url = new URL(`${url.origin}${url.pathname}?${new_params}`);
console.log(new_url.href);
// https://example.com/?a=hello&b=world&c=a&d=2&e=false
// Here it is as a function that accepts (URL, Record<string, string>)
const addSearchParams = (url, params = {}) =>
new URL(
`${url.origin}${url.pathname}?${new URLSearchParams([
...Array.from(url.searchParams.entries()),
...Object.entries(params),
])}`,
);
使用上面数据:
const url = new URL("https://example.com/?a1=hello&b1=world");
console.log("url==>", url);
const addSearchParams = (url, params = {}) =>
new URL(
`${url.origin}${url.pathname}?${new URLSearchParams([
...Array.from(url.searchParams.entries()),
...Object.entries(params)
])}`
);
console.log("return url==>", addSearchParams(url, query).toString());
返回结果:`
https://example.com/?a1=hello&1b=world&a=a&b=1&c=1%2C2%2C3%2C... `
解析
const { searchParams } = new URL(url);
const result = {}
for(let [key, value] of searchParams){
result[key] = value;
}
return result;
}
parse 之后:
{ a1: 'hello',
'1b': 'world',
a: 'a',
b: '1',
c: '1,2,3,[object Object]',
d: '[object Object]',
e: 'https://www.baidu.com?a=1&b=1#tag',
'a?.b': 'a_b' }
总结
URL
和URLSearchParams
为我们实现 URL 参数格式化和解析提供了新的思路- 总体来看推荐使用
qs
这个库来实现,它的支持能力最强
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。