axios会对url的参数进行encodeURIComponent编码问题

先来确定一个事情:

let a = [1]
let b = JSON.stringify(a) 	  // '[1]'
let c = encodeURIComponent(b) // '%5B1%5D'
let d = encodeURIComponent(c) // '%255B1%255D'

这里需要留意一下abcd转码之后的格式,后面会用到。

然后问题来了,现在需要和后端对接一个接口,在swagger调试的结果类似这样

https://www.baidu.com/s?arr=%5B1%5D

经过分析可以看出%5B1%5DencodeURIComponent(JSON.stringify([1]))之后的结果。

那么前端可以用axios对接接口,例如:

axios({
  url: 'https://www.baidu.com/s',
  method: 'get',
  params: {
    arr: encodeURIComponent(JSON.stringify([1]))
  },
})

但是在谷歌浏览器上点击F12,你会发现发送出去的链接是:

https://www.baidu.com/s?arr=%255B1%255D

%255B1%255DencodeURIComponent(encodeURIComponent(JSON.stringify([1])))之后的结果。

这里大家可能会想,这个应该是axios内部进行了转码造成的,那我们再来看一下这个例子:

axios({
  url: 'https://www.baidu.com/s',
  method: 'get',
  params: {
    arr: JSON.stringify([1])
  },
})

这个链接会输出什么呢,如果结果是https://www.baidu.com/s?arr=%5B1%5D,那么就能证明,确实是axios内部进行了转码,但是结果很奇怪,输出的链接是https://www.baidu.com/s?arr=[1],竟然没有进行转码!

也就是在使用axios时候,parms的参数是{arr: JSON.stringify([1])}时,url不转码。parms的参数是{arr: encodeURIComponent(JSON.stringify([1, 2, 3]))}时,会进行转码!

我们只能打断点看一下源码了!

git clone https://github.com/axios/axios.git

我clone的axios版本是1.4.0
请添加图片描述
可以看到axios里面使用的是XHR,也就是ajax,在我画红框的地方有一个buildURL方法,然后把params传入了这个方法,来看一下buildURL具体实现
在这里插入图片描述
可以看到里面有一个encode方法,里面还是用到了encodeURIComponent,也就是说对于放在params里面的内容,都会转码,至于为什么JSON.stringify([1])没有被转码,其实可以看一下这句话:

function encode(val) {
  return encodeURIComponent(val).
    replace(/%3A/gi, ':').
    replace(/%24/g, '$').
    replace(/%2C/gi, ',').
    replace(/%20/g, '+').
    replace(/%5B/gi, '[').
    replace(/%5D/gi, ']');
}

也就是说JSON.stringify([1])先被转码为‘%5B1%5D’,然后遇到了replace(/%5B/gi, ‘[’)replace(/%5D/gi, ‘]’),所有就又转回了[1]

那么如何阻止axios的自动转码呢?这里给出3中方法。

  1. 可以通过使用 paramsSerializer 修改默认行为,例如:
axios({
  url: 'https://www.baidu.com/s',
  method: 'get',
  params: {
    arr: JSON.stringify([1])
  },
  paramsSerializer: (params) => {
    let arr = []
    for (let key in params) arr.push(key + '=' + encodeURIComponent(params[key]))
    return arr.join('&')
  },
})

这样输出的url格式就是:

https://www.baidu.com/s?arr=%5B1%5D

这里我们使用了paramsSerializer,其实可以看我的第一张图片,buildURL的第三个入参就是paramsSerializer,也就是如果外界传入了paramsSerializer,那么_encode就是paramsSerializer,如果没传_encode就是内置的encode。

  1. 或者不用params传参,直接把参数拼接到url后面,例如使用qs:
axios({
  url: 'https://www.baidu.com/s?' + qs.stringify({ arr: JSON.stringify([1]) }),
  method: 'get',
})

这样输出的格式也是

https://www.baidu.com/s?arr=%5B1%5D
  1. 使用URLSearchParams
const params = new URLSearchParams();
params.append('arr', JSON.stringify([1]));

axios({
  url: 'https://www.baidu.com/s',
  params,
  method: 'get',
})

也可以参考官网看一下axios

  • 21
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值