让URLSearchParams帮你生成和解析参数字符串

 

让URLSearchParams帮你生成和解析参数字符串

让URLSearchParams帮你生成和解析参数字符串

让URLSearchParams帮你生成和解析参数字符串

Henry

不会做一手好菜的全栈前端不是好产品经理

50 人赞了该文章

无论在 Node.js 程序还是 HTML 前端程序里,我们都免不了像下面这样手工拼 URL 搜索字符串(URL Search String,或称 Query String):

// 备注:习惯上我们用 k 和 p 分别代表 keywords 和 pageIndex 的缩写:
function getQueryString(params) {
   if (params) {
     const {
       keywords,
       pageIndex = 1
     } = params;
     return `?k=${encodeURIComponent(keywords || '')}&p=${pageIndex}`;
   }
   throw new Error('"params" 参数不能为空。');
}

// 返回“?k=%E5%85%B3%E9%94%AE%E5%AD%97&p=1”
console.log(getQueryString({ keywords: '关键字', pageIndex: 1 }));

如果你逐行阅读上面的代码,不难发现这段程序并不是很严谨,而且虽然只有两个参数,但是却需要考虑参数为 null 或 undefined,此外还需通过 encodeURIComponent() 函数来处理 UTF-8 编码问题。

而将 JSON 对象转为 URL 字符串还并不是最大的难题,如何从 location.search 解析出参数才是更大的问题。例如,从 react-router v4 开始,不再支持对 URL 参数,你需要自己写代码从 location.search 中解析出你需要的参数。

 


URLSearchParams

那么你可能会想有没有横跨不同浏览器和 Node.js 的现成解决方案或者开源项目呢?答案一定是有的,而且还是一个标准这就是 URLSearchParams(浏览器端文档 Node.js 文档)。

 

浏览器支持列表

让URLSearchParams帮你生成和解析参数字符串

让URLSearchParams帮你生成和解析参数字符串

引用

浏览器代码

// 如果需要支持较低版本的 PC 浏览器,需要额外安装和引用 polyfill:
// $ npm install --save url-search-params
// import URLSearchParams from 'url-search-params';

const urlSearchParams = new URLSearchParams();

Node.js 代码

const { URLSearchParams } = require('url');

const urlSearchParams = new URLSearchParams();

 

生成搜索字符串

const params = new URLSearchParams();
params.set('k', '关键字');       // 设置参数
params.set('p', 1);             // 支持 Boolean、Number 等丰富类型
console.log(params.toString()); // k=%E5%85%B3%E9%94%AE%E5%AD%97&p=1

 

解析搜索字符串

const params = new URLSearchParams('k=%E5%85%B3%E9%94%AE%E5%AD%97&p=1');
console.log(params.get('k'));   // 返回字符串“关键字”,支持自动 UTF-8 解码
console.log(params.get('p'));   // 返回字符串“1”
console.log(params.get('xxx')); // 如果没有 xxx 这个键,则返回 null
console.log(params.has('xxx')); // 当然也可以通过 has() 方法查询是否存在指定的键
console.log(params.keys());     // 返回一个 ES6 Iterator,内含 ['k', 'p']
console.log(params.values());   // 返一个 ES6 Iterator,内含 ['关键字', '1']
console.log(params.entries());  // 与 Map.prototype.entries() 类似

 


 

怎么样是不是无论生成还是解析都非常简单?而更妙的是它还完美支持 URL 搜索参数列表!

URL 搜索参数列表

相信不少同学都有过不知该如何在 HTTP GET 参数中传递数组的经历,我看到过不少人使用的这种方式:

http://example.com/search?brands=bmw,audi,mercedes

 

事实上,上面这种方式是不够标准的,并且需要处理原本字符串中就包含“,”的情况,而在业界广为推荐的范式是这样的:

http://example.com/search?brands=bmw&brands=audi&brands=mercedes

 

在 Node.js 中,以 express 为例,可以通过下面的方法获得上面 brands 参数的值:

app.get('/search', (req, res) => {
  console.log(req.query.brands); // 直接返回一个数组 ['bmw', 'audi', 'mercedes']
  ...
});

 

那么我们应该如何通过 URLSearchParams 来生成及解析这种标准参数形式呢?使用 append() 和 getAll() 方法就行:

let params = new URLSearchParams();
// 通过 append() 方法添加所有的选项值
params.append('brands', 'bmw');
params.append('brands', 'audi');
params.append('brands', 'mercedes');
const searchString = params.toString();

// 解析也同样简单
params = new URLSearchParams(searchString);
console.log(params.getAll('brands')); // 返回一个数组 ['bmw', 'audi', 'mercedes']

 

写在最后

URLSearchParams 无疑是前端做查询字符串拼接、特别是实现前端路由的好帮手。这里还要啰嗦一句,由于还在试验阶段,因此 Node.js、Chrome、Firefox 以及各种 Polyfill 类库的实现略有不同,例如:

const params = new URLSearchParams({
  k: '关键字',
  p: 1
});
console.log(params.toString());

在 Chrome 和 Node.js 上可以获得我们预期的结果,而在 FireFox 和 Polyfill 类库上则不支持 JSON 的构造函数,起初还差点害我出了一次生产事故,另外 UC 浏览器的实现也有不同(不支持“?”开头的字符串作为构造参数),因此大家在初期使用的时候要格外小心,不多说了,直接给出 URLSearchParams API 文档地址: