有一段时间没写过技术干货文了,这两天恰好遇到一个之前没太在乎的一个功能实现--前端获取URL传递的参数前端
毕竟平时都是在后台处理,掉了一堆头发后,想一想仍是写出来跟大家分享一下,之后要是大家遇到了也有个参考正则表达式
要只是获取一些常规字符串到没什么难的,关键还有些乱七八糟的需求,什么同一个参数名传递了屡次啊,传数组啊。搞来搞去就写了一大堆数组
先说说思路吧,若是你看这文章是想要解决问题,拿着代码直接用的话,就直接看最后面的Code实现以及使用方法吧浏览器
给你一个以下的URL:微信
将URL里传递的参数转换为object
对象,这样咱们在使用参数的时候也更为方便函数
我曾屡次强调框架思惟,如今遇到这个问题了,咱们就拿框架思惟来分析一下,该怎样才能快速解决学习
首先是要了解咱们的目的是什么?目的很简单,取得URL内传递的参数,而且解析成对象ui
接着再分析咱们如今知道些什么?有一串URLurl
咱们再来分析,若是从URL中得到传递的参数,也就是为了达到目的,咱们该作些什么?
URL的特征咱们大体都知道,就是第一个?
后面的字符串,都是传递的参数,可是有个特殊状况请不要忘记了,URL后面有时候会带上一个#
,而#
后面的内容,并非咱们要传递的参数,而是网页位置的标识符
若是URL中包含了#
,咱们只须要解析?
到#
之间的字符串就能够了,若是不包含,那么第一个?
后全部的内容都是咱们须要解析的
你可能以为我是在说废话,这么明显的事情,只要不是白痴都能看得懂
我固然知道,只要不是白痴都能看得懂,但我为何要强调呢?由于咱们想要快速的解决问题,必须具有框架思惟,也能够说是工程思惟
你可能有会说,这么简单的问题须要这样分析么?咱们一看就知道了,闹闹你这是杀鸡用牛刀
虽然说是杀鸡用牛刀,可要想培养本身的工程思惟,那么必须保持刻意训练,直到随手拈来
好了,分析完后,咱们按照上面的思路来逐步实现,实现的时候可能会遇到其它的问题,到时候再分析,再解决
毕竟再牛逼的工程师,也不会在动手前就想的面面俱到,只能是在动手实现前尽量的考虑周到,遇到问题时再快速的迭代更新
先用JS拿到URL,若是函数传参了URL,那就用参数。若是没传参,就使用当前页面的URL
var queryString = url ? url.split('?')[1] : window.location.search.slice(1);
复制代码
若是后面的字符串存在#
,咱们还得将#
后面的字符串去掉,由于#
后面的内容并非咱们须要获取的参数,而是网页位置的标识符
queryString = queryString.split('#')[0];
复制代码
好了,把干扰的部分都移除后,咱们能够开始安心的解析参数了,先将传递的参数分红数组
var arr = queryString.split('&');
复制代码
如今咱们能够得到一个字符串数组
['product=shirt', 'color=blue', 'newuser', 'size=m']
复制代码
将字符串拆分红数组后,咱们经过建立一个对象,用来存储咱们全部的参数
var obj = {};
复制代码
咱们能够经过遍历数组arr
,将它拆分红键值对。把这个字符串作成key:value
的对象
var a = arr[i].split('=');
复制代码
接下来就是要为每个变量key
分配对应的值value
,若是咱们获得的value
不是一个正确的参数,咱们就用true
来表示这个参数名存在,固然了,你也能够根据本身的实际状况来作改变
var paramName = a[0];
var paramValue = typeof(a[1]) === 'undefined' ? true : a[1];
复制代码
在这里我只是对undefined
作了标记,若是是NaN
,我是直接拿它当字符串处理了
在这里有一个小坑得提醒一下,咱们在调用函数,获取对象取值的时候,若是URL传递的key
为大写,咱们取对象时写的小写,那么结果就是为undefined
好比URL为http://NaoNao.com/?NamE=NaoNao
,若是不作大小写的处理,调用对象取值时getAllUrlParams().NamE
才能取到值NaoNao
,若是作了处理,咱们使用时只须要所有写成小写/大写便可,例如getAllUrlParams().name
我在这就所有转为小写了,若是你对大小写要求区分,那到时候把这段Code给去掉就行了
paramName = paramName.toLowerCase();
if (typeof paramValue === 'string') paramValue = paramValue.toLowerCase();
复制代码
接下来咱们就要去处理咱们接受到的paramValue
,这些参数多是索引数组,非索引数组,又或者是常规字符串
若是是索引数组,咱们须要将paramValue
转换成数组,而且将索引对应的值,放入索引对应的位置
若是是非索引数组,咱们就要将paramValue
放到数组中
若是只是常规的字符串,咱们就须要为咱们的对象obj
建立一个常规的属性,并为其分配值。
若是这个key已经存在,那么咱们就要将现有的paramValue
从key:value
转换为数组,并将它放到数组中
拿几个实际案例,感觉一下咱们要作什么吧
// 索引数组
getAllUrlParams('http://NaoNao.com/?colors[0]=red&colors[2]=green&colors[6]=blue');
// { "colors": [ "red", null, "green", null, null, null, "blue" ] }
// 非索引数组
getAllUrlParams('http://NaoNao.com/?colors[]=red&colors[]=green&colors[]=blue');
// { "colors": [ "red", "green", "blue" ] }
// 屡次传递同一个key
getAllUrlParams('http://NaoNao.com/?colors=red&colors=green&colors=blue');
// { "colors": [ "red", "green", "blue" ] }
// 传递了key,可是没传value
getAllUrlParams('http://NaoNao.com/?product=shirt&color=blue&newuser&size=m');
// { "product": "shirt", "color": "blue", "newuser": true, "size": "m" }
复制代码
我作这写判断时用的是正则表达式,在这里就不解释正则了。。。毕竟解释起来篇幅就太长了,能看懂就尽可能看吧
每一个正则要解析什么,在注释中都写了例子,稍微了解点正则表达式的同窗,多半也能看懂的
对应的代码实现以下:
// 若是paramName以方括号结束, e.g. colors[] or colors[2]
if (paramName.match(/\[(\d+)?\]$/)) {
// 若是paramName不存在,则建立key
var key = paramName.replace(/\[(\d+)?\]/, '');
if (!obj[key]) obj[key] = [];
// 若是是索引数组 e.g. colors[2]
if (paramName.match(/\[\d+\]$/)) {
// 获取索引值并在对应的位置添加值
var index = /\[(\d+)\]/.exec(paramName)[1];
obj[key][index] = paramValue;
} else {
// 若是是其它的类型,也放到数组中
obj[key].push(paramValue);
}
} else {
// 处理字符串类型
if (!obj[paramName]) {
// 若是若是paramName不存在,则建立对象的属性
obj[paramName] = paramValue;
} else if (obj[paramName] && typeof obj[paramName] === 'string') {
// 若是属性存在,而且是个字符串,那么就转换为数组
obj[paramName] = [obj[paramName]];
obj[paramName].push(paramValue);
} else {
// 若是是其它的类型,仍是往数组里丢
obj[paramName].push(paramValue);
}
}
复制代码
若是你的URL的传参包含了一些特殊字符,好比空格。例如url="NaoNao.com/?name=Nao%20Nao"
,拿到对象值以后,是须要解码后才能得到正确的值的
var original = getAllUrlParams().name; // 'Nao%20Nao'
var decode = decodeURIComponent(original); // 'Nao Nao'
复制代码
下面是JS的具体的完整实现,大家复制回去就能够用
function getAllUrlParams(url) {
// 用JS拿到URL,若是函数接收了URL,那就用函数的参数。若是没传参,就使用当前页面的URL
var queryString = url ? url.split('?')[1] : window.location.search.slice(1);
// 用来存储咱们全部的参数
var obj = {};
// 若是没有传参,返回一个空对象
if (!queryString) {
return obj;
}
// stuff after # is not part of query string, so get rid of it
queryString = queryString.split('#')[0];
// 将参数分红数组
var arr = queryString.split('&');
for (var i = 0; i < arr.length; i++) {
// 分离成key:value的形式
var a = arr[i].split('=');
// 将undefined标记为true
var paramName = a[0];
var paramValue = typeof (a[1]) === 'undefined' ? true : a[1];
// 若是调用对象时要求大小写区分,可删除这两行代码
paramName = paramName.toLowerCase();
if (typeof paramValue === 'string') paramValue = paramValue.toLowerCase();
// 若是paramName以方括号结束, e.g. colors[] or colors[2]
if (paramName.match(/\[(\d+)?\]$/)) {
// 若是paramName不存在,则建立key
var key = paramName.replace(/\[(\d+)?\]/, '');
if (!obj[key]) obj[key] = [];
// 若是是索引数组 e.g. colors[2]
if (paramName.match(/\[\d+\]$/)) {
// 获取索引值并在对应的位置添加值
var index = /\[(\d+)\]/.exec(paramName)[1];
obj[key][index] = paramValue;
} else {
// 若是是其它的类型,也放到数组中
obj[key].push(paramValue);
}
} else {
// 处理字符串类型
if (!obj[paramName]) {
// 若是若是paramName不存在,则建立对象的属性
obj[paramName] = paramValue;
} else if (obj[paramName] && typeof obj[paramName] === 'string') {
// 若是属性存在,而且是个字符串,那么就转换为数组
obj[paramName] = [obj[paramName]];
obj[paramName].push(paramValue);
} else {
// 若是是其它的类型,仍是往数组里丢
obj[paramName].push(paramValue);
}
}
}
return obj;
}
复制代码
这个函数该怎么使用呢?
直接把URL参数当成对象调用就OK咯~
以文章开篇的URL为例子
// http://NaoNao.com/?product=shirt&color=blue&newuser&size=m#Hello
getAllUrlParams().product; // 'shirt'
getAllUrlParams().color; // 'blue'
getAllUrlParams().newuser; // true
getAllUrlParams().NB; // undefined
getAllUrlParams('http://NaoNao.com/?NaoNao=shuai').NaoNao; // shuai
复制代码
若是咱们不须要考虑IE这种妖娆贱货,以及一些很是老版本浏览器,就用浏览器内URLSearchParams
的接口吧。。。这个接口能够直接拿取URL内的参数
// URL is http://NaoNao.com/?product=shirt&color=blue&newuser&size=m
const urlParams = new URLSearchParams(window.location.search);
// 判断参数是否存在
console.log(urlParams.has('product')); // true
// 获取参数对应的值
console.log(urlParams.get('product')); // "shirt"
复制代码
这个接口还提供了更多成熟的方法,好比keys()
,Values()
,还有entries()
,这个接口该怎么使用,直接去看官方文档就行了,用起来仍是很虚浮的