当前位置: 首页 > Web前端 > HTML

如何在URL中插入参数

时间:2023-04-02 11:17:32 HTML

有一个很简单的需求如下:给你一个URL,在里面插入一些参数,返回一个新的URL,如何实现呢?这里的参数,有时称为query,有时称为params,一般称为search,参考http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument中的key1和key2。最近在对接阿里云的金融级实人认证,在通过认证成功回调页面时遇到了这样的问题。第一层:直接拼importqsfrom'query-string'functionresolve(url){constparams=qs.stringify({a:1,b:2})//a=1&b=2returnurl+'?'+params}在实际业务中,90%的场景都是这样写的,但是如果url的值是这样的:http://taobao.com/?c=3&d=4,那么最后的结果就是http:///taobao.com/?c=3&d=4?a=1&b=2解析在该网址中搜索,结果为{c:'3',d:'4?a=1',b:'2',}显然不符合预期。第二层:兼容现有searchimportqsfrom'query-string'functionresolve(url){constparams=qs.stringify({a:1,b:2})//a=1&b=2returnurl+(url.includes('?')?'&':'?')+params}貌似问题解决了,很多人只考虑这一层,但是现在有这样一个url:http://taobao。com/#/xxx尤其是单页应用,这种形式的hash路由很常见。如果简单的拼接在URL的末尾:http://taobao.com/#/xxx?a=1&b=2,解析这个URL中的搜索,结果是{}。可以看到拼接的参数根本没有跑起来。进去搜索。也就是说,只要在URL中出现#,下面呢?不会被视为搜索的初始标志,而是散列的一部分。如果网址比较复杂,比如:http://taobao.com/?c=3&d=4#/xxx,上面的拼接就会变成:http://taobao.com/?c=3&d=4#/xxx&a=1&b=2不仅没有按预期插入参数,而且还破坏了原来的哈希结构。其实以vue-router为例,?在哈希恰好在其路由系统中使用。例如:http://example.com/user/:foo/info?c=3&d=4#/xxx?a=1&b=2在vue-router中,xxx是路由的路径,foo称为params,a和b称为query,分别通过route.params和route.query获取。#后可以连接任何字符串。?a=1&b=2只是路由器自己定义的一组内部规则,为路由参数服务。而c和d是search,需要从location.search中解析出来。如果后端收到这样的GET请求,hash后面的一切都会被丢弃,只能接收并解析search。所以#后面不能出现插入参数,也就是简单的在URL后面拼接字符串是不行的。第三层:只处理searchimportqsfrom'query-string'functionresolve(url){constparams=qs.stringify({a:1,b:2})//a=1&b=2consturlObj=newURL(url)urlObj.search+=urlObj.search.startsWith('?')?'&':'?+paramsreturnurlObj.href}这样可以处理上面的复杂情况。使用URL对象是一种巧妙的方法。将url字符串解析成URL对象后,可以只修改其search属性,不影响其他部分。在axios的源码中,我们可以看到另一种标准实现:functionbuildURL(url,params){if(!params){returnurl;}//params序列化过程略varhashmarkIndex=url.indexOf('#');如果(hashmarkIndex!==-1){url=url。切片(0,hashmarkIndex);}url+=(url.indexOf('?')===-1?'?':'&')+params;返回网址;};思路很简单,就是在url末尾插入序列化的params,但是如果有hash就插入hash之前,如果有搜索就用&代替连接符。相关链接:什么是URLURL对象Vue-router路由对象