Henry Henry
  • JavaScript
  • TypeScript
  • Vue
  • ElementUI
  • React
  • HTML
  • CSS
  • 技术文档
  • GitHub 技巧
  • Nodejs
  • Chrome
  • VSCode
  • Other
  • Mac
  • Windows
  • Linux
  • Vim
  • VSCode
  • Chrome
  • iTerm
  • Mac
  • Obsidian
  • lazygit
  • Vim 技巧
  • 分类
  • 标签
  • 归档
  • 网站
  • 资源
  • Vue 资源
GitHub (opens new window)

Henry

小学生中的前端大佬
  • JavaScript
  • TypeScript
  • Vue
  • ElementUI
  • React
  • HTML
  • CSS
  • 技术文档
  • GitHub 技巧
  • Nodejs
  • Chrome
  • VSCode
  • Other
  • Mac
  • Windows
  • Linux
  • Vim
  • VSCode
  • Chrome
  • iTerm
  • Mac
  • Obsidian
  • lazygit
  • Vim 技巧
  • 分类
  • 标签
  • 归档
  • 网站
  • 资源
  • Vue 资源
GitHub (opens new window)
  • JavaScript

    • js 编码指南
    • 日期使用斜杠 点 中划线分隔的不同
    • forEach 会改变原数组值吗
    • 前端表单验证常用的正则表达式 - reg
    • JS 如何取得 URL 里的参数
      • 用框架思维分析问题
      • JS 获取 URL 参数的过程
      • 具体实现以及使用方式
      • 不兼容 IE 的解决方案
    • JavaScript 数组去重
    • JavaScript 循环中断研究与总结-关键字篇
    • JavaScript 循环中断研究与总结-用法篇
    • js 中的 Error
    • 跳出 forEach
    • Location 对象
    • Date 方法预览
    • Reg 正则中的问题
    • JavaScript toFixed() 方法
    • query 和 params 的使用区别
    • axios post 请求中下载文件流
    • 实用的 js 技巧
    • JS 之数组的几个不 low 操作
    • 深入浅出深拷贝与浅拷贝
    • 如何实现一个深拷贝
    • 使用 iframe 中的一些问题
    • 在 js 中更好地使用数组
    • echarts 在坐标轴两侧各增加一格坐标
    • 从头认识js的事件循环模型
    • moment 根据周截至日算出指定月有几周及开始结束日期
    • 正则 reg 中 /number 的用法
    • 正则 reg 中 match 和 exec 异同
  • TypeScript

  • Vue

  • ElementUI

  • React

  • AntD

  • 前端
  • JavaScript
Henry
2019-03-14
目录
用框架思维分析问题
JS 获取 URL 参数的过程
具体实现以及使用方式
不兼容 IE 的解决方案

JS 如何取得 URL 里的参数

上篇简单介绍了一下 Location 对象, 并封装了一个简单处理 URL 的方法, 本篇封装一个处理复杂 URL 的方法

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

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

# 用框架思维分析问题

给你一个如下的 URL:

http://example.com:1234/test/t.asp?a=aa&b=bb&c&d=dd#Hello

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

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

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

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

我们再来分析, 如果从 URL 中获得传递的参数, 也就是为了达到目的, 我们该做些什么?

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

如果 URL 中包含了 # , 我们只需要解析 ? 到 # 之间的字符串就可以了, 如果不包含, 那么第一个 ? 后所有的内容都是我们需要解析的

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

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

# JS 获取 URL 参数的过程

先用 JS 拿到 URL, 如果函数传参了 URL, 那就用参数. 如果没传参, 就使用当前页面的 URL

url = url || window.location.href
var queryString = url.split('?')[1]
1
2

如果后面的字符串存在 # , 我们还得将 # 后面的字符串去掉, 因为 # 后面的内容并不是我们需要获取的参数, 而是网页位置的标识符

queryString = queryString.split('#')[0]
1

好了, 把干扰的部分都移除后, 我们可以开始安心的解析参数了, 先将传递的参数分成数组

var arr = queryString.split('&')
1

现在我们可以获得一个字符串数组

;['a=aa', 'b=bb', 'c', 'd=dd']
1

将字符串拆分成数组后, 我们通过创建一个对象, 用来存储我们所有的参数

var obj = {}
1

我们可以通过遍历数组 arr , 将它拆分成键值对. 把这个字符串做成 key:value 的对象

var a = arr[i].split('=')
1

接下来就是要为每一个变量 key 分配对应的值 value , 如果我们得到的 value 不是一个正确的参数, 我们就用 true 来表示这个参数名存在, 当然了, 你也可以根据自己的实际情况来做改变

var paramName = a[0]
var paramValue = typeof a[1] === 'undefined' ? true : a[1]
1
2

在这里我只是对 undefined 做了标记, 如果是 NaN , 我是直接拿它当字符串处理了

在这里有一个小坑得提醒一下, 我们在调用函数, 获取对象取值的时候, 如果 URL 传递的 key 为大写, 我们取对象时写的小写, 那么结果就是为 undefined

比如 URL 为 http://example.com:1234/test/t.asp?TeSt=TEst , 如果不做大小写的处理, 调用对象取值时 getAllUrlParams().TeSt 才能取到值 TEst , 如果做了处理, 我们使用时只需要全部写成小写/大写即可, 例如 getAllUrlParams().test

我在这就全部转为小写了, 如果你对大小写要求区分, 那到时候把这段 Code 给去掉就好了

paramName = paramName.toLowerCase()
1

接下来我们就要去处理我们接受到的 paramValue , 这些参数可能是索引数组, 非索引数组, 又或者是常规字符串

  • 如果是索引数组, 我们需要将 paramValue 转换成数组, 并且将索引对应的值, 放入索引对应的位置

  • 如果是非索引数组, 我们就要将 paramValue 放到数组中

  • 如果只是常规的字符串, 我们就需要为我们的对象 obj 创建一个常规的属性, 并为其分配值.

  • 如果这个 key 已经存在, 那么我们就要将现有的 paramValue 从 key:value 转换为数组, 并将它放到数组中

拿几个实际案例, 感受一下我们要做什么吧

// 索引数组
getAllUrlParams('http://example.com/?colors[0]=red&colors[2]=green&colors[6]=blue')
// { "colors": [ "red", null, "green", null, null, null, "blue" ] }

// 非索引数组
getAllUrlParams('http://example.com/?colors[]=red&colors[]=green&colors[]=blue')
// { "colors": [ "red", "green", "blue" ] }

// 多次传递同一个key
getAllUrlParams('http://example.com/?colors=red&colors=green&colors=blue')
// { "colors": [ "red", "green", "blue" ] }

// 传递了key,但是没传value
getAllUrlParams('http://example.com/?product=shirt&color=blue&newuser&size=m')
// { "product": "shirt", "color": "blue", "newuser": true, "size": "m" }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

对应的代码实现如下:

// 如果 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)
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

如果你的 URL 的传参包含了一些特殊字符, 比如空格. 例如 url="example.com/?name=na%20me" , 拿到对象值之后, 是需要解码后才能获得正确的值的

var original = getAllUrlParams().name // 'na%20me'
var decode = decodeURIComponent(original) // 'na me'
1
2

# 具体实现以及使用方式

下面是 JS 的具体的完整实现, 你们复制回去就可以用

function getAllUrlParams(url) {
  // 用 JS 拿到 URL,如果函数接收了 URL,那就用函数的参数。如果没传参,就使用当前页面的 URL
  url = url || window.location.href
  var queryString = url.split('?')[1]
  // 用来存储我们所有的参数
  var obj = {}
  // 如果没有传参,返回一个空对象
  if (!queryString) {
    return obj
  }
  // # 后的内容不是我们需要的
  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()
    // 如果 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
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

这个函数该怎么使用呢?

直接把 URL 参数当成对象调用就 OK 咯~

以文章开篇的 URL 为例子

var url = 'http://example.com:1234/test/t.asp?a=aa&b=bb&c&d=dd#Hello'

var urlParams = getAllUrlParams(url)

urlParams.a // 'aa'
urlParams.b // 'bb'
urlParams.c // true
urlParams.NB // undefined
1
2
3
4
5
6
7
8

你可以在下面输入框中输入需要查询的 url 来体验一下!

  

# 不兼容 IE 的解决方案

如果我们不需要考虑 IE 这种妖娆贱货, 以及一些非常老版本浏览器, 就用浏览器内 URLSearchParams (opens new window) 的接口吧... 这个接口可以直接拿取 URL 内的参数

var a = document.createElement('a')
a.href = 'http://example.com:1234/test/t.asp?a=aa&b=bb&c&d=dd#Hello'

var urlParams = new URLSearchParams(a.search) // 使用 search 时注意 # 和 ? 的先后位置

// 判断参数是否存在
console.log(urlParams.has('a')) // true
// 获取参数对应的值
console.log(urlParams.get('a')) // 'aa'
1
2
3
4
5
6
7
8
9

这个接口还提供了更多成熟的方法, 比如 keys() , Values() , 还有 entries() , 这个接口该怎么使用, 直接去看官方文档就好了, 用起来还是很虚浮的

编辑 (opens new window)
#Js#Location
上次更新: 11/12/2020, 6:27:50 AM
前端表单验证常用的正则表达式 - reg
JavaScript 数组去重

← 前端表单验证常用的正则表达式 - reg JavaScript 数组去重→

最近更新
01
搭配 Jenkins 实现自动化打包微前端多个项目
09-15
02
自动化打包微前端多个项目
09-15
03
el-upload 直传阿里 oss 并且显示自带进度条和视频回显封面图
06-05
更多文章>
0 comments
Anonymous
Markdown is supported

Be the first person to leave a comment!

Theme by Vdoing | Copyright © 2017-2025 HenryTSZ | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式