一、URL Query的基础概念
URL的query(查询字符串)是URL中?
之后的部分,用于传递参数,格式为key=value&key2=value2
。例如:
https://example.com/path?name=张三&age=25&hobbies=reading,music
核心需求:从URL中解析出这些参数,用于前端路由、数据筛选或接口请求。
二、原生JavaScript解析方法
1. 使用URLSearchParams(ES6+推荐方案)
// 解析当前页面URL的query
const url = new URL(window.location.href);
const params = new URLSearchParams(url.search);
// 获取单个参数
const name = params.get('name'); // "张三"
const age = params.get('age'); // "25"
// 获取多个同名参数(如hobbies)
const hobbies = params.getAll('hobbies'); // ["reading", "music"]
// 转换为对象
const paramsObj = Object.fromEntries(params.entries());
// { name: "张三", age: "25", hobbies: "reading,music" }
// 检查参数是否存在
params.has('age'); // true
2. 手动解析字符串(兼容旧浏览器)
function getQueryParams(url = window.location.href) {
const search = url.split('?')[1];
if (!search) return {};
const params = {};
search.split('&').forEach(param => {
const [key, value] = param.split('=');
if (key) {
// 解码URI编码(如%20转空格)
params[key] = decodeURIComponent(value || '');
}
});
return params;
}
// 使用示例
const params = getQueryParams();
console.log(params.name); // "张三"
console.log(params.hobbies); // "reading,music"
三、框架与库的解析方案(工程实践)
1. React Router解析(常用场景)
import { useLocation } from 'react-router-dom';
function MyComponent() {
const location = useLocation();
const searchParams = new URLSearchParams(location.search);
// 获取参数
const page = searchParams.get('page') || 1;
const keyword = searchParams.get('keyword') || '';
return (
<div>
页码: {page}, 关键词: {keyword}
</div>
);
}
2. Vue Router解析(Vue 3示例)
<template>
<div>
<p>ID: {{ id }}</p>
<p>搜索词: {{ keyword }}</p>
</div>
</template>
<script setup>
import { useRoute } from 'vue-router';
const route = useRoute();
const id = route.query.id;
const keyword = route.query.keyword || '默认搜索词';
</script>
3. 第三方库(如qs)
import qs from 'qs';
// 解析query字符串
const search = window.location.search.slice(1); // 去除?
const params = qs.parse(search, {
ignoreQueryPrefix: true,
decode: true
});
// 处理数组参数(如hobbies=reading&hobbies=music)
const hobbies = params.hobbies || [];
四、问题
1. 问:如何处理query中的数组参数?
- 答:
- URLSearchParams.getAll():
// URL: ?hobbies=reading&hobbies=music const hobbies = params.getAll('hobbies'); // ["reading", "music"]
- 自定义解析规则:
若参数格式为?hobbies=reading,music
,可通过逗号分割:const hobbies = (params.hobbies || '').split(',');
- 第三方库支持:
qs库可自动解析数组参数(需配置arrayFormat: 'repeat'
)。
- URLSearchParams.getAll():
2. 问:如何处理URI编码的参数?
- 答:
- 编码场景:参数包含特殊字符(如空格、中文)时会被编码为
%20
、%E4%B8%AD%E6%96%87
- 解码方法:
decodeURIComponent(params.get('key'))
:解码单个参数- 手动解析时使用
decodeURIComponent(value)
(如前文手动解析函数)
- 编码场景:参数包含特殊字符(如空格、中文)时会被编码为
3. 问:前端路由如何与query参数联动?
- 答:
- React场景:
// 跳转时携带query参数 history.push({ pathname: '/search', search: `?keyword=${encodeURIComponent('前端')}&page=2` }); // 或使用useSearchParams Hook(React Router 6+) import { useSearchParams } from 'react-router-dom'; function SearchPage() { const [searchParams, setSearchParams] = useSearchParams(); searchParams.set('page', '2'); setSearchParams(searchParams); }
- Vue场景:
// 编程式导航携带query this.$router.push({ path: '/search', query: { keyword: '前端', page: 2 } });
- React场景:
五、实战场景与边界处理
1. 动态生成带query的URL
// 场景:搜索条件变化时更新URL
function updateUrlWithParams(params) {
const url = new URL(window.location.href);
Object.keys(params).forEach(key => {
if (params[key] !== undefined) {
url.searchParams.set(key, params[key]);
} else {
url.searchParams.delete(key); // 删除未定义的参数
}
});
window.history.pushState(null, '', url.href);
}
// 使用示例
updateUrlWithParams({ keyword: '性能优化', page: 3 });
2. 处理多级嵌套参数
// URL: ?user[name]=张三&user[age]=25
function parseNestedParams(params) {
const result = {};
for (const [key, value] of params.entries()) {
let current = result;
const keys = key.split('[');
// 处理最后一个键(可能带])
const lastKey = keys.pop().replace(']', '');
// 构建嵌套对象
keys.forEach(k => {
if (!current[k]) current[k] = {};
current = current[k];
});
current[lastKey] = value;
}
return result;
}
const nestedParams = parseNestedParams(params);
// { user: { name: "张三", age: "25" } }
六、总结
“从URL的query中取值可分为三类方案:
- 原生JS:使用
URLSearchParams
(ES6+)或手动解析字符串,前者支持数组参数和便捷API; - 框架集成:React Router用
useLocation
,Vue Router用$route.query
,适配路由场景; - 第三方库:如qs库支持嵌套参数解析和编码处理。
实际项目中,我会根据场景选择方案:简单场景用原生URLSearchParams
,复杂参数处理用qs库,路由联动则优先使用框架提供的API。同时需注意URI编码/解码、数组参数处理和历史记录更新,确保参数解析的准确性和用户体验的一致性。”