拼接 URL 查询参数总出错?不如用 URLSearchParams
一、背景:查询字符串是最容易被手写坏的地方
前后端联调里,给接口拼查询参数几乎是天天都干的事。最早大家习惯用字符串硬拼:'?page=' + page + '&size=' + size。这种做法有两个坑:一是参数里有中文、空格、特殊符号时,不做 encodeURIComponent 就会丢数据或者把 & 截断;二是参数多了以后,拼接顺序、是否带 ?、是否为空,全靠人脑记,很容易拼出 ?&size=10 这种脏链接。我以前就因为少写了编码,把一个搜索词里带 # 的请求整条发错,调了半天才发现是前端拼串的问题。
后来我基本不再手写,直接用浏览器和 Node 都内置的 URLSearchParams。它把编码、增删改查、序列化全包了,出来的字符串永远是合规的。这篇文章把它的常用方法和几个容易踩的点讲清楚。
二、核心代码:增删改查一行搞定
最基础的用法,创建一个实例然后往里塞键值对:
const params = new URLSearchParams();
params.append('page', 1);
params.append('size', 10);
params.append('keyword', '前端 性能'); // 含空格
console.log(params.toString());
// page=1&size=10&keyword=%E5%89%8D%E7%AB%AF+%E6%80%A7%E8%83%BD
注意输出里中文和空格已经被自动编码,空格在查询串里按表单约定编码成 +(加号),不用我们再手动 encodeURIComponent。从已有的查询串解析也很简单,直接把 location.search 丢进去:
const params = new URLSearchParams(window.location.search);
const page = params.get('page'); // 字符串,注意类型
const hasTag = params.has('tag');
params.set('page', 2); // set 会覆盖同名的旧值
params.delete('size');
console.log(params.toString());
get 永远返回字符串,数字类型要自己 Number() 转一下,这是第一个容易忽略的点。set 和 append 不一样:append 是追加,同一个 key 会出现两次;set 是覆盖成唯一一个。
三、遍历、批量构造与和 URL 配合
需要拿到所有参数时,可以用 entries 或者 forEach 遍历:
const params = new URLSearchParams('a=1&a=2&b=3');
for (const [key, val] of params.entries()) {
console.log(key, val); // a 1 / a 2 / b 3
}
console.log(params.getAll('a')); // ['1', '2'],同名取全部
如果参数本来就在一个对象里,可以一步构造:new URLSearchParams({ page: 1, size: 10 }),传普通对象即可。要拼回完整地址,配合 URL 对象最稳妥,不会把 ? 写错位置:
const url = new URL('https://api.xxx.com/list');
url.search = params.toString(); // 等价于 url.searchParams = params
console.log(url.href); // https://api.xxx.com/list?page=1&size=10
这里有个细节:url.search 赋值时会自动处理 ?,不用我们手动加。反向读取也方便,url.searchParams.get('page') 直接拿。
四、几个真正会让你栽跟头的地方
第一,数组参数别用 set。后端要 tag=a&tag=b 这种重复 key 时,必须用 append 多次,用 set('tag', ['a','b']) 会被序列化成 tag=a%2Cb,后端解析会失真。
第二,空格的编码。URLSearchParams.toString() 按 application/x-www-form-urlencoded 约定把空格序列化成 +(加号),而不是 %20。绝大多数后端框架解析查询串时都会把 + 还原成空格,没问题;但若遇到老后端只认 %20,或者你要手动把查询拼进 URL 路径而非查询部分,需要 replace(/\+/g, '%20') 转一下,否则空格会失真。
第三,空值要清理。拼参数前最好把 null、undefined、空字符串过滤掉,否则会出现 &name= 这种无效字段,某些后端会报错。我习惯先 Object.entries 过滤再构造。
第四,它只管查询串,不管 hash。改了 location.hash 不会影响 search,两者互不影响,别混为一谈。
第五,Node 端同样可用。在服务端拼回调地址、OAuth 跳转链接时也能用,行为和浏览器一致,不用引第三方库。
五、小结
URLSearchParams 是处理查询参数的标准答案,编码、增删改查、序列化都帮你做对,比手写字符串拼接稳得多。记住几个关键点:用 append 处理同名多值、用 set 处理单值、取值记得 Number() 转型、拼完整地址交给 URL 对象、发老接口时注意 + 和 %20 的差异。把它当成拼接查询参数的默认工具,能少掉很多莫名其妙的联调 bug。
- 点赞
- 收藏
- 关注作者
评论(0)