今天在地铁上刷到一个面试视频,博主提问:获取url中参数的新方法?
关于这个问题,平时在项目中都是高频使用,按照以前jq时代,那就是原生自己造个轮子就用了,后面有了框架,基本都是使用别人造好的轮子,直接拿来就用,也就很少去考虑这些。
本着不了解,有兴趣,所以就趁着午休时间学习了解一下,顺便把以前的方式也给复习了一遍。
http://localhost:8887/fill?calcUnitId=290&checkType=1&cycleType=BY_YEAR&orgId=10018066&pageType=1&preSubTaskId&smModelId=666&status=%E6%9C%AA%E5%A1%AB%E6%8A%A5&subtaskId=47957&taskName=2025y×tamp=1704681001789
采用以前的方式获取参数那就简单了,总的来说的,可以分为几个步骤
采用上面的示例逐步进行分析,下面的步骤将每一步获取到的结果都进行了打印,便于对应学习。
步骤一
以 ? 为界限进行分割
, 拿到所有的参数
const url_split = url.split('?');
console.log('url_split::', url_split);
const params = url_split[1];
conole.log('params::', params)
步骤二
以 & 为界限分割
,将每个参数以 key = value 的形式展现得到一个数组
const url_split = url.split('?');
console.log('url_split::', url_split);
const params = url_split[1];
console.log('params::', params);
// 新增
var paramsKeyValue = params.split('&');
console.log('paramsKeyValue::', paramsKeyValue);
步骤三
创建 params 对象,便于数据拿取
const url_split = url.split('?');
console.log('url_split::', url_split);
const params = url_split[1];
console.log('params::', params);
const paramsKeyValue = params.split('&');
console.log('paramsKeyValue::', paramsKeyValue);
// 新增
const params = {};
步骤四
循环得到的数组 paramsKeyValue
,再次将每一项以 =
进行分割;
其实步骤三和步骤四可以归属为一步,这里只是将其细分了一下。
如果确定要进行函数封装,那么建议将步骤三提到步骤一前面,便于函数返回结果;
const url_split = url.split('?');
console.log('url_split::', url_split);
const params = url_split[1];
console.log('params::', params);
const paramsKeyValue = params.split('&');
console.log('paramsKeyValue::', paramsKeyValue);
const params = {};
// 新增
paramsKeyValue.forEach((item) => {
const [key, value] = item.split('=');
params[key] = value;
});
console.log('params::', params);
到此就算获取到完整的参数对象了,整体不复杂,里面呢关于数组循环获取值这些完全可以再次进行优化处理,使其更加的严谨健壮,可以从一下方面进行优化,比如:
针对上面提到的优化点,其实在官网已经给提供了新的API【URLSearchParams】。
下面是对他的一些描述,大家看看就好,最好是自己动手敲上一遍。
URLSearchParams
接口定义了一些实用的方法来处理 URL 的查询字符串。
URLSearchParams() 返回一个 URLSearchParams 对象
。
var params = new URLSearchParams(url);
console.log('params::', params)
从返回的 URLSearchParams 对象
的原型上可以看到有如下方法:
接下来就一一打印输出看看,每个方法都是怎使用的。
该接口不继承任何属性。
基础使用
根据MDN所说,使用 for ( const item of params) {}
打印看看具体都是些什么内容。
var params = new URLSearchParams(url);
console.log('params::', params)
// 新增
for (const item of params) {
console.log('atrrs22222222:key--', item)
};
// 输出如下结果:
/*
VM13196:43 atrrs22222222:key-- (2) ['http://localhost:8887/fill?calcUnitId', '290']
VM13196:43 atrrs22222222:key-- (2) ['checkType', '1']
VM13196:43 atrrs22222222:key-- (2) ['cycleType', 'BY_YEAR']
VM13196:43 atrrs22222222:key-- (2) ['orgId', '10018066']
VM13196:43 atrrs22222222:key-- (2) ['pageType', '1']
VM13196:43 atrrs22222222:key-- (2) ['preSubTaskId', '']
VM13196:43 atrrs22222222:key-- (2) ['smModelId', '666']
VM13196:43 atrrs22222222:key-- (2) ['status', '未填报']
VM13196:43 atrrs22222222:key-- (2) ['subtaskId', '47957']
VM13196:43 atrrs22222222:key-- (2) ['taskName', '2025y']
VM13196:43 atrrs22222222:key-- (2) ['timestamp', '1704681001789']
*/
从打印的结果这么一看好像是一个二维的数组。
但是这里要注意一下,这里有一点不一样的地方,请看输出第一项,他的这个key('http://localhost:8887/fill?calcUnitId')
居然包含了问号及前面所有域名地址信息,这个就不合理了对吧。
那这是为什么呢?
原因很简单哈,因为这里使用的url 是一个完整的地址 + 参数,如果在实际项目中则采用 window.location.search
去获取参数,然后再给放到 new URLSearchParams()
里面作为参数,这样解析出来后就不带前面的域名地址信息。
URLSearchParams.get()
获取指定搜索参数的第一个值。
var params = new URLSearchParams(url);
console.log('params::', params.get('参数名'));
URLSearchParams.getAll()
获取指定搜索参数的所有值,返回是一个数组。
var params = new URLSearchParams(url);
console.log('params::', params.getAll('参数名'));
// 例:
var url = '?calcUnitId=001&calcUnitId=290&checkType=1'
var params = new URLSearchParams(url);
console.log('atrrs: ', params.getAll('calcUnitId'))
// VM13388:5 atrrs: (2) ['001', '290']
这个 getAll() 感觉有些鸡肋哈,不知道会在什么情况下会使用,如果有懂的同学,可以评论区多多留言。
URLSearchParams.keys()
返回iterator 此对象包含了键/值对的所有键名。
var params = new URLSearchParams(url);
console.log('params::', params.keys());
for (const item of params.keys()) {
console.log('item:', item)
}
URLSearchParams.values()
返回iterator 此对象包含了键/值对的所有值。
var params = new URLSearchParams(url);
console.log('params::', params.values());
for (const item of params.values()) {
console.log('item:', item)
}
URLSearchParams.entries()
返回一个 iterator (迭代器)
可以遍历所有键/值对的对象。
var params = new URLSearchParams(url);
console.log('params::', params.entries());
// 打印结果:params:: URLSearchParams Iterator {}
// 打印结果中明确的指出了迭代器,既然如此,那就采用循环把每一项都给打印出来
关于迭代器相关知识讲起来也是可以单独写一篇文章了,并且网上也比较多,都比较全面,所以就自行GPT,这里就不再过多赘述。
获取每一项数据:
for (const item of params.entries()) {
const [key, value] = item;
console.log('atrrs: ' + item + ', value:' + [key, value])
}
/*
VM13266:9 atrrs: calcUnitId,290, value:calcUnitId,290
VM13266:9 atrrs: checkType,1, value:checkType,1
VM13266:9 atrrs: cycleType,BY_YEAR, value:cycleType,BY_YEAR
VM13266:9 atrrs: orgId,10018066, value:orgId,10018066
VM13266:9 atrrs: pageType,1, value:pageType,1
VM13266:9 atrrs: preSubTaskId,, value:preSubTaskId,
VM13266:9 atrrs: smModelId,666, value:smModelId,666
VM13266:9 atrrs: status,未填报, value:status,未填报
VM13266:9 atrrs: subtaskId,47957, value:subtaskId,47957
VM13266:9 atrrs: taskName,2025y, value:taskName,2025y
VM13266:9 atrrs: timestamp,1704681001789, value:timestamp,1704681001789
*/
URLSearchParams.set()
设置一个搜索参数的新值,假如原来有多个值将删除其他所有的值。
var url = '?calcUnitId=001&calcUnitId=290&checkType=1'
var params = new URLSearchParams(url);
params.set('checkType', 124)
for (const item of params.entries()) {
console.log('item:', item)
}
/*
VM13715:9 item: (2) ['calcUnitId', '001']
VM13715:9 item: (2) ['calcUnitId', '290']
VM13715:9 item: (2) ['checkType', '124']
*/
var url = '?calcUnitId=001&calcUnitId=290&checkType=1'
var params = new URLSearchParams(url);
params.set('calcUnitId', 124)
for (const item of params.entries()) {
console.log('item:', item)
}
/*
VM13718:9 item: (2) ['calcUnitId', '124']
VM13718:9 item: (2) ['checkType', '1']
*/
URLSearchParams.sort()
按键名排序。
var params = new URLSearchParams(url);
console.log('atrrs: ', params.sort())
URLSearchParams.toString()
返回搜索参数组成的字符串,可直接使用在 URL 上。
var params = new URLSearchParams(url);
console.log('atrrs: ', params.toString())
// atrrs: calcUnitId=001&calcUnitId=290&checkType=1&cycleType=BY_YEAR&orgId=10018066&pageType=1&preSubTaskId=&smModelId=666&status=%E6%9C%AA%E5%A1%AB%E6%8A%A5&subtaskId=47957&taskName=2025y×tamp=1704681001789
URLSearchParams.append(key,value)
插入一个指定的键/值对作为新的搜索参数。
var params = new URLSearchParams(url);
// 新增
params.append('aa', 1111);
for (const item of params.keys()) {
console.log('item:', item)
}
/*
VM13590:9 item: calcUnitId
VM13590:9 item: checkType
VM13590:9 item: cycleType
VM13590:9 item: orgId
VM13590:9 item: pageType
VM13590:9 item: preSubTaskId
VM13590:9 item: smModelId
VM13590:9 item: status
VM13590:9 item: subtaskId
VM13590:9 item: taskName
VM13590:9 item: timestamp
VM13590:9 item: aa // 新添加的aa
*/
URLSearchParams.delete(key)
从搜索参数列表里删除指定的搜索参数及其对应的值。
var params = new URLSearchParams(url);
// 删除
params.delete('aa');
URLSearchParams.has()
返回 Boolean 判断是否存在此搜索参数。
var params = new URLSearchParams(url);
console.log('params::', params.has('参数名'));
URLSearchParams 构造函数不会解析完整 URL,但是如果字符串起始位置有 ? 的话会被去除。
上面这句话直白的翻译就是:
如果参数 ?calcUnitId=290&checkType=1&cycleType=BY_YEAR&orgId=10018066&pageType=1&preSubTaskId&smModelId=666&status=%E6%9C%AA%E5%A1%AB%E6%8A%A5&subtaskId=47957&taskName=2025y×tamp=1704681001789'
是这种前面带 ?
的,在使用的时候会自动去掉 ?
。