需求
如何全面准确地获取URL上的查询参数,包括hash前面和后面的部分。比如:
https://example.com/test?type=card#/about?name=tom
这里需要获取到type=card和name=tom这两个参数。
首先,location.search只能获取到问号后面的查询参数,也就是hash前面的部分。对于上面的URL,location.search会返回"?type=card"。而hash后面的部分,也就是#后面的内容,可以通过location.hash获取,但里面的查询参数location.search是拿不到的。
要同时获取hash前和hash后的查询参数,这时候就需要分别处理这两个部分的参数,然后将它们合并起来。
可以按照以下步骤实现:
- 解析
location.search中的参数:这部分是标准的查询参数。 - 解析
location.hash中的参数:需要从hash中提取路径后的查询参数。 - 合并两部分参数,处理同名键时,hash中的参数覆盖search中的参数。
实现
function getAllQueryParams() {
const params = {};
// 处理search部分的参数
const searchParams = new URLSearchParams(window.location.search);
for (const [key, value] of searchParams) {
params[key] = value;
}
// 处理hash部分的参数
const hash = window.location.hash.substring(1);
const queryIndex = hash.indexOf('?');
if (queryIndex !== -1) {
const hashQuery = hash.substring(queryIndex + 1);
const hashParams = new URLSearchParams(hashQuery);
for (const [key, value] of hashParams) {
params[key] = value; // hash参数覆盖search参数
}
}
return params;
}
// 测试
const queryParams = getAllQueryParams();
console.log(queryParams.type); // 输出 "card"
console.log(queryParams.name); // 输出 "tom"
多个问号
搜了网上有些实现会根据?分割location.hash中的查询参数,但如果hash中的查询参数中有多个问号?就不对了,比如:
https://example.com/test?type=card#/about?name=tom?asd=123
以下两种结果哪种是正确的呢?
{
"type": "card",
"name": "tom?asd=123"
}
{
"type": "card",
"name": "tom"
}
我们先验证一下,假如多个问号出现在location.search中,比如:
https://example.com/?name=tom?asd=123
URLSearchParams处理的结果是什么呢?
new URLSearchParams(location.search).get('name')
'tom?asd=123'
所以,第一种结果才是正确的,不能通过问号?分割查询参数,而是读取location.hash中第一个问号?作为查询参数的开头,后面的问号?都是查询参数的值。