前言
我们每一天都在和url打交道,如果让我们将一个url解析成为一个对象呢?我们又该如何操作?废话不说,请移步至正文,且看如何解析!
正文
在解析之前我们先来看看一个url的组成是什么样子的
const url = 'https://www.domain.com/order/detail?user=admin&id=123&id=234&city=%E5%8D%97%E6%98%8C&enabled'
这里我们列举一个假的url.一个url被分为协议部分,域名,路径,携带参数.大致是这么四部分,但是我们拿到的一个url可以是字符串的形式.所以我们的工作任务就是对这个字符串下手.
我们打造一个prase()的函数
function parse(url) {
}
那么既然我们拿到的url是一个字符串,我们需要将字符串里面的内容分割出来,那么能拿到字符串中的部分内容有slice(),split()等方法,slice()是需要我们具体到字符串的某一位置,split()则是通过什么分割出来.所以这里我们使用split()通过特定的字符将内容分割出来.
首先我们需要获取到的是协议部分.
我们清晰地知道协议部分和域名是通过://隔开来的,所以协议部分我们用split('://')将整个url分割成为两个数组,protocolArr数组下标0就是协议部分
const protocolArr = url.split('://')
const protocol = protocolArr[0]
第二步我们是需要获取到域名
这里我们用红线除去我们已经获取到的协议部分,剩下的部分就是protocolArr[1],那么我们如何获取到域名呢?这时我们就不需要思考分解域名,而是域名与下一部分的'分割线'是什么,我们可以看到分割线是/
const hostnameArr = protocolArr[1].split('/')
const hostname = hostnameArr[0]
这时我们得到的hostnameArr长这个样子['www.domain.com', 'order', 'detail?user=adminxxxxxx'],所以我们也只需要拿到hostnameArr[0]也就会拿到域名
拿完域名写一部就是拿路径了,我们都知道路径不可能就是有但是/order一部分,经常都是/order/detail或者更多的情况出现,所以我们就不能依旧使用/.那么路径和写一部分的参数是通过什么分割的呢.是?我们先试用?分割看看会得到什么.这里由于protocolArr[1]依旧是包含路径部分的,我们就偷会懒不额外创建变量了.
const pathArr = protocolArr[1].split('?')
我们拿到的结果是['www.domain.com/order/detail','user=admin&id=123&id=234&city=%E5%8D%97%E6%98%8C&enabled']
事实证明我们很好的将参数部分分割出来了,但是我们需要的路径并没有分割出来,那能怎么办呢,我们就多分割一下就好了.pathArr[0].split(hostname)[1]我们拿到下标0'www.domain.com/order/detail'通过域名分割就好了.
最后一分部就是获取参数了.参数部分就是pathArr[1]每一个参数都是通过&进行分离的.那么我们将参数部分变成数组const queryArr = pathArr[1].split('&')得到就是['user=admin', 'id=123', 'id=234',enabled']
然后创建一个参数对象const query = {}.使用forEach遍历数组queryArr.这里我们先判断参数的格式,毕竟有些参数是不长'user=admin'这样的,也就是不是用等号的.
if (!item.includes('=')) {
query[item] = true
return
}
对于这一类的参数我们就直接设置它的value值为true.那么其余的都是有等号的.我们使用item.split('=')将其分割,这里的item使我们forEach遍历的item.每一个item都是数组queryArr中的值.我们将其分割成key和value.但是这里我们需要对value额外处理一下乱码的问题.那么在js中有这么一个decodeURI方法可以帮助我们解决乱码问题.
const itemArr = item.split('=')
const key = itemArr[0]
const value = decodeURI(itemArr[1])
这里的itemArr长这个样子,我们使用'user=admin'来举例,['user','admin']所以这里的key和value就可以很好的取到对应的值了.最后我们将键值对存到对象中,我们需要考虑一个问题就是一个键有多个值,比如这样
那么我们就需要把这个key打造成一个数组.
if (query[key] !== undefined) {
if (!Array.isArray(query[key])) {
query[key] = [query[key]]
}
query[key].push(value)
} else {
query[key] = value
}
第一步我们先判断有没有这个属性,如果有的话,就检查是不是一个数组,如果不是,那么就把query[key]打造成数组,如果是一个数字,那就直接push了.最后没有这个属性就直接赋值了.
至此我们就基本上写好解析一个url的代码了,最后异步就是返回数据,下面是完整的代码.
const url = 'https://www.domain.com/order/detail?user=admin&id=123&id=234&city=%E5%8D%97%E6%98%8C&enabled'
console.log(parse(url));
function parse(url) {
const protocolArr = url.split('://')
const protocol = protocolArr[0]
const hostnameArr = protocolArr[1].split('/')
const hostname = hostnameArr[0]
const pathArr = protocolArr[1].split('?')
const path = pathArr[0].split(hostname)[1]
const queryArr = pathArr[1].split('&') // ['user=admin', 'id=123', 'xxx']
const query = {}
queryArr.forEach(item => {
if (!item.includes('=')) {
query[item] = true
return
}
const itemArr = item.split('=')
const key = itemArr[0]
const value = decodeURI(itemArr[1])
if (query[key] !== undefined) {
if (!Array.isArray(query[key])) {
query[key] = [query[key]]
}
query[key].push(value)
} else {
query[key] = value
}
});
return {
protocol,
hostname,
path,
query
}
}
输出结果返回如下:
至此本文就结束了,希望本篇文章对您有所帮助,感谢阅读!!