JS如何取得URL里的参数?

栏目: 后端 · 前端 · 发布时间: 5年前

内容简介:有一段时间没写过技术干货文了,这两天刚好遇到一个以前没太在意的一个功能实现--毕竟平时都是在后台处理,掉了一堆头发后,想想还是写出来跟你们分享一下,以后要是你们遇到了也有个参考要只是获取一些常规字符串到没什么难的,关键还有些乱七八糟的需求,什么同一个参数名传递了多次啊,传数组啊。搞来搞去就写了一大堆
JS如何取得URL里的参数?

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

毕竟平时都是在后台处理,掉了一堆头发后,想想还是写出来跟你们分享一下,以后要是你们遇到了也有个参考

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

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

用框架思维分析问题

给你一个如下的URL:

NaoNao.com/?product=sh…

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

我曾多次强调框架思维,现在遇到这个问题了,我们就拿框架思维来分析一下,该怎样才能快速解决

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

接着再分析 我们现在知道些什么 ?有一串URL

我们再来分析,如果从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() ,这个接口该怎么使用,直接去看官方文档就好了,用起来还是很虚浮的

JS如何取得URL里的参数?

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

深入分析Java Web技术内幕(修订版)

深入分析Java Web技术内幕(修订版)

许令波 / 电子工业出版社 / 2014-8-1 / CNY 79.00

《深入分析Java Web技术内幕(修订版)》新增了淘宝在无线端的应用实践,包括:CDN 动态加速、多终端化改造、 多终端Session 统一 ,以及在大流量的情况下,如何跨越性能、网络和一个地区的电力瓶颈等内容,并提供了比较完整的解决方案。 《深入分析Java Web技术内幕(修订版)》主要围绕Java Web 相关技术从三方面全面、深入地进行了阐述。首先介绍前端知识,即在JavaWeb ......一起来看看 《深入分析Java Web技术内幕(修订版)》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具