JS如何取得URL里的参数?

有一段时间没写过技术干货文了,这两天恰好遇到一个之前没太在乎的一个功能实现--前端获取URL传递的参数前端

毕竟平时都是在后台处理,掉了一堆头发后,想一想仍是写出来跟大家分享一下,之后要是大家遇到了也有个参考正则表达式

要只是获取一些常规字符串到没什么难的,关键还有些乱七八糟的需求,什么同一个参数名传递了屡次啊,传数组啊。搞来搞去就写了一大堆数组

先说说思路吧,若是你看这文章是想要解决问题,拿着代码直接用的话,就直接看最后面的Code实现以及使用方法吧浏览器

用框架思惟分析问题

给你一个以下的URL:微信

NaoNao.com/?product=sh…框架

将URL里传递的参数转换为object对象,这样咱们在使用参数的时候也更为方便函数

我曾屡次强调框架思惟,如今遇到这个问题了,咱们就拿框架思惟来分析一下,该怎样才能快速解决学习

首先是要了解咱们的目的是什么?目的很简单,取得URL内传递的参数,而且解析成对象ui

接着再分析咱们如今知道些什么?有一串URLurl

咱们再来分析,若是从URL中得到传递的参数,也就是为了达到目的,咱们该作些什么?

URL的特征咱们大体都知道,就是第一个?后面的字符串,都是传递的参数,可是有个特殊状况请不要忘记了,URL后面有时候会带上一个#,而#后面的内容,并非咱们要传递的参数,而是网页位置的标识符

若是URL中包含了#咱们只须要解析?#之间的字符串就能够了,若是不包含,那么第一个?后全部的内容都是咱们须要解析的

你可能以为我是在说废话,这么明显的事情,只要不是白痴都能看得懂

我固然知道,只要不是白痴都能看得懂,但我为何要强调呢?由于咱们想要快速的解决问题,必须具有框架思惟,也能够说是工程思惟

你可能有会说,这么简单的问题须要这样分析么?咱们一看就知道了,闹闹你这是杀鸡用牛刀

虽然说是杀鸡用牛刀,可要想培养本身的工程思惟,那么必须保持刻意训练,直到随手拈来

好了,分析完后,咱们按照上面的思路来逐步实现,实现的时候可能会遇到其它的问题,到时候再分析,再解决

毕竟再牛逼的工程师,也不会在动手前就想的面面俱到,只能是在动手实现前尽量的考虑周到,遇到问题时再快速的迭代更新

JS获取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已经存在,那么咱们就要将现有的paramValuekey: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的解决方案

若是咱们不须要考虑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(),这个接口该怎么使用,直接去看官方文档就行了,用起来仍是很虚浮的

微信扫码关注公众号「闹闹吃鱼」,每周都有好分享,还可领取学习资源哦~不只仅只是技术!

相关文章
相关标签/搜索