这篇文章发布于 2019年08月26日,星期一,00:13,归类于 JS API。 阅读 68193 次, 今日 8 次 26 条评论
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=8907
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。
一、先快速了解这两个API干嘛用的
以前我们要对地址栏中的URL地址进行分析处理,需要自己进行字符串分析,例如:
https://www.zhangxinxu.com/wordpress/?s=url
我们想要知道s
参数后面的值是什么,往往需要进行字符切割匹配,要么正则匹配。
实际上,现在,浏览器已经有了内置的API接口可以对URL进行处理,这个API就是URLSearchParams()
以及URL()
。
例如获取s
的查询参数值,可以直接下面这样:
new URL('https://www.zhangxinxu.com/wordpress/?s=url').searchParams.get('s');
或者:
new URLSearchParams('?s=url').get('s');
二、先来了解下URLSearchParams()语法
语法
// URL查询字符串 var myUrlSearchParams = new URLSearchParams(strSearchParams); // 查询字符序列 var myUrlSearchParams = new URLSearchParams(arrSearchSequence); // 查询键值对象 var myUrlSearchParams = new URLSearchParams(objSearchKeyValue);
参数
- strSearchParams
-
URL查询字符串。使用示意:
var params1 = new URLSearchParams('?s=url');
或者对当前地址栏地址的查询字符串进行实例化:var params2 = new URLSearchParams(location.search);
- arrSearchSequence
-
数组形式的查询字符序列。例如:
var params3 = new URLSearchParams([['s', 'url'], ['someId', 1]]);
- objSearchKeyValue
-
键值对形式的查询对象。例如:
var params4 = new URLSearchParams({"s": "url", "someId": 2})
三、URLSearchParams实例方法们
上面执行new URLSearchParams()
的返回值myUrlSearchParams
就是一个URLSearchParams实例。
这个URLSearchParams实例包含众多方法,具体如下:
- URLSearchParams.append(name, key)
- 添加新的键值对作为查询参数。例如:
var params = new URLSearchParams('?s=url'); // 也可以没有问号直接's=url' params.append('from', 'zxx'); // 此时的查询字符串是:'s=url&from=zxx'
- URLSearchParams.delete(name)
- 删除已存在的查询参数。例如:
var params = new URLSearchParams('?s=url'); params.delete('s'); // 此时的查询字符串是:''
- URLSearchParams.entries()
- 返回查询参数们的迭代器对象,我们可以迭代该迭代器对象获得所有的键值对。例如使用for..of:
var searchParams = new URLSearchParams("s=url&from=zxx"); // 显示所有的键值对 for (var pair of searchParams.entries()) { console.log(pair[0]+ ', '+ pair[1]); }
控制台输入结果示意:
- URLSearchParams.forEach(callback)
- 此方法可以遍历查询对象。
其中
callback
是遍历方法,支持两个参数,分别是每个键值对的值和键。示意:var searchParams = new URLSearchParams("s=url&from=zxx"); // 输出值和键的内容 searchParams.forEach(function(value, key) { console.log(value, key); });
- URLSearchParams.get(name)
- 返回指定关键字对象的值。例如:
var params = new URLSearchParams('s=url&from=zxx'); params.get('s'); // 返回值是:'url'
如果没有对应的值,则返回
null
。 - URLSearchParams.getAll(name)
- 以数组形式返回所有当前查询关键字对应的值,例如:
var params = new URLSearchParams('s=url&s=urlsearchparams&from=zxx'); params.getAll('s'); // 返回值是:['url', 'urlsearchparams']
- URLSearchParams.has(name)
- 返回布尔值,
true
或者false
,是否包含某个查询关键字。var params = new URLSearchParams('?s=url'); params.has('s') == true; // true
- URLSearchParams.keys()
- 返回一个迭代器对象,允许迭代该对象中所有的关键字。使用示意:
var searchParams = new URLSearchParams("s=url&from=zxx"); // 显示所有的键 for (var key of searchParams.keys()) { console.log(key); }
- URLSearchParams.values()
- 返回一个迭代器对象,允许迭代该对象中所有的关键字值。使用示意:
var searchParams = new URLSearchParams("s=url&from=zxx"); // 显示所有的值 for (var value of searchParams.values()) { console.log(value); }
- URLSearchParams.set(name, value)
- 有则替换,无则加冕。例如:
var params = new URLSearchParams('s=url&s=urlsearchparams&from=zxx'); params.set('s', 'css世界'); params.getAll('s'); // 返回值是:['css世界']
可以看到会替换之前所有的
's'
查询参数值。下面这个例子展示“无则加冕”:var params = new URLSearchParams('s=url'); params.set('from', 'zxx'); params.toString(); // 结果是:'s=url&from=zxx'
也就是原本没有对应参数的时候会添加这个参数。 - URLSearchParams.sort()
- 方法将此对象中包含的所有键/值对就地排序,并返回
undefined
。排序顺序根据键的Unicode码位。该方法使用一种稳定的排序算法(即保留具有相同键的键/值对之间的相对顺序)。例如:var searchParams = new URLSearchParams('c=4&a=2&b=3&a=1'); // 键值对排序 searchParams.sort(); // 显示排序后的查询字符串 console.log(searchParams.toString()); // 结果是:a=2&a=1&b=3&c=4
- URLSearchParams.toString()
- 把URLSearchParams对象转换成查询字符串。这个代码示意上面多次出现,这里不重复展示。
URLSearchParams()兼容性
Edge17+支持。
四、再来了解下URL()语法
URL接口用于解析、构造、规范化和编码URL。其构造的实例支持若干属性和方法,可以用来读写URL相关的属性值。我们甚至可以把文件内容作为URL的一部分进行呈现。
在使用URL()
之前,建议先做个浏览器支持与否的判断,例如:
if (window.URL) {
// ...
}
另外,URL接口支持在web workers中使用。
语法
var myUrl = new URL(url, [base])
参数
- url
- 相对地址或者绝对地址。如果是相对地址,需要设置
base
参数,如果是绝对地址,则会忽略base
设置。我们也可以使用URL对象作为url参数。此时作用的值是URL对象中的href
属性值。 - base
- 如果URL地址是相对地址,则需要这个参数,作用是作为相对计算的基础地址。我们也可以使用URL对象作为base参数,此时作用的值是URL对象中的
href
属性值。如果不设置该参数,则会按照空字符串''
进行处理。
如果参数值无法组合成完整URL地址,则会报TypeError错误。
测试与用法示意
基本使用示意:
var base = 'https://www.zhangxinxu.com'; // 结果是:https://www.zhangxinxu.com/study console.log(new URL('study', base).href); // 结果是:https://www.zhangxinxu.com/study console.log(new URL('/study', base).href);
可以直接使用URL对象作为参数:
var base = 'https://www.zhangxinxu.com'; var urlFromBase = new URL('study', base); // 结果是:https://www.zhangxinxu.com/study console.log(new URL(urlFromBase).href); // 结果是:https://www.zhangxinxu.com/wordpress console.log(new URL('wordpress', urlFromBase).href);
下面是带有较深层级base地址和不同相对地址形式的测试:
var base = 'https://www.zhangxinxu.com/study/a/b/c'; // 结果是:https://www.zhangxinxu.com/study/a/b/sp/icon console.log(new URL('sp/icon', base).href); // 结果是:https://www.zhangxinxu.com/study/a/b/sp/icon // 上下结果对比表明./和裸露相对地址没有区别 console.log(new URL('./sp/icon', base).href); // 结果是:https://www.zhangxinxu.com/study/a/sp/icon // 向上一层URL层级深度 console.log(new URL('../sp/icon', base).href); // 结果是:https://www.zhangxinxu.com/study/a/b/sp/icon // 层级按照斜杠来算的 console.log(new URL('../sp/icon', base + '/').href); // 结果是:https://www.zhangxinxu.com/sp/icon // 斜杠开头表示跟地址开始匹配 console.log(new URL('/sp/icon', base).href);
眼见为实,下面的是控制台输出结果:
下面是不同域名之间的测试:
var base = 'https://www.zhangxinxu.com'; // 结果是:http://image.zhangxinxu.com和https://image.zhangxinxu.com // 没有协议的url认为是相对地址,协议取自base地址 console.log(new URL('//image.zhangxinxu.com', 'http://www.zhangxinxu.com').href); console.log(new URL('//image.zhangxinxu.com', 'https://www.zhangxinxu.com').href); // 结果是:https://image.zhangxinxu.com // 这里url是完整的绝对地址,因此,忽略后面的base参数 console.log(new URL('https://image.zhangxinxu.com', base).href);
这是运行后的结果:
下面是出错的测试:
// 没有绝对地址,会报错
console.log(new URL('').href);
console.log(new URL('//image.zhangxinxu.com').href);
五、URL实例对象的属性和方法
new URL()返回值就是一个实例对象,包括下面这些属性和方法。
属性
已知有URL地址如下:
var url = new URL('https://www.zhangxinxu.com:80/wordpress/?s=url#comments'); var ftp = new URL('ftp://username:password@192.168.1.1/path/file');
- hash
- URL地址中的锚链值,包含字符串
'#'
,例如这里url.hash
的返回值是'#comments'
。 - host
- URL地址中host主机地址,包括协议端口号,这里
url.host
的返回值是'www.zhangxinxu.com:80'
。 - hostname
- URL地址中主机名称,不包括端口号,这里
url.hostname
的返回值是'www.zhangxinxu.com'
。 - href
- 完成的URL地址。
- origin [只读]
- 返回URL地址的来源,会包含URL协议,域名和端口。这里
url.origin
的返回值是'https://www.zhangxinxu.com:80'
。 - password
- 返回URL地址域名前的密码。ftp协议中比较常见。这里
ftp.password
的返回值是'password'
。 - username
- 返回URL地址域名前的用户名。ftp协议中比较常见。这里
ftp.username
的返回值是'username'
。 - pathname
- 返回URL中的目录+文件名。例如这里
ftp.pathname
的返回值是'/path/file'
。 - port
- 返回URL地址中的端口号。例如这里
url.port
的返回值是'80'
,ftp.port
的返回值是''
。 - protocol
- 返回URL地址的协议,包括后面的冒号
':'
。例如这里url.protocol
的返回值是'https:'
,ftp.protocol
的返回值是'ftp:'
。 - search
- 返回URL地址的查询字符串,如果有参数,则返回值以问号
'?'
开头。例如这里url.search
的返回值是'?s=url'
。 - searchParams
- 返回一个URLSearchParams对象,可以调用URLSearchParams对象各种方法,对查询字符串进行非常方便的处理。例如我们想要知道查询关键字
s
对应的值,可以:url.searchParams.get('s');
方法
- toString()
- 返回的完整的URL地址,你可以理解为URL.href的另外一种形式,不过这个只能输出,不能修改值。
- toJSON()
- 同样返回完整的URL地址,返回的字符串和
href
属性一样。
静态方法
- URL.createObjectURL(object)
- 可以把File,Blob或者MediaSource对象变成一个一个唯一的blob URL。其中参数
object
可以是File,Blob或者MediaSource对象。 - URL.revokeObjectURL(objectURL)
- 撤消之前使用
URL.createObjectURL()
创建的URL对象。其中参数objectURL
表示之前使用URL.createObjectURL()
创建的URL返回值。
静态方法实际使用案例一则
我们使用Ajax请求一个跨域图片避免canvas跨域生成问题的时候可以使用这两个静态方法:
var xhr = new XMLHttpRequest(); xhr.onload = function () { var url = URL.createObjectURL(this.response); var img = new Image(); img.onload = function () { // 此时你就可以使用canvas对img为所欲为了 // ... code ... // 图片用完后记得释放内存 URL.revokeObjectURL(url); }; img.src = url; }; xhr.open('GET', url, true); xhr.responseType = 'blob'; xhr.send();
兼容性
Edge 12+支持。
六、这两个JS API的polyfill
从兼容性表可以看出,URLSearchParams Edge 17才开始支持,而URL 从Edge 12才开始支持,似乎兼容性不佳,但是,这并不妨碍我们在实际项目中使用,为什么呢?因为有polyfill。
这里有一个一直支持到ES7最新规范的URL和URLSearchParams polyfill项目:https://github.com/lifaon74/url-polyfill
按照官方说法,兼容到IE 10+。
IE9究竟支不支持,还是仅仅是部分支持,我大致简单测试了一下,结论如下:
除了URL()几个静态方法以外的基本使用IE9都是支持的!
对于我来说,够用了够用了。
如果以后实际应用发现其他细节再更新。
七、结语
web这块,无论是CSS,HTML还是JS API都在不断进步,标准且跨平台,以前很多需要自定义的方法和特性,现在浏览器都已经原生支持,以前的那些语言框架价值越来越低。
是时候开始尝试拥抱原生,辛苦地学习与积累,简单且轻松的实现,面向产品,面向用户,立足未来,方能穿越长河。
那些咨询我前端问题的小伙伴,不用再问我任何关于Vue和React的问题了,我全部用都没用过,以后也不会用,不是我的方向,也不是未来的方向。
本文为原创文章,欢迎分享,勿全文转载,如果内容你实在喜欢,可以加入收藏夹,永不过期,而且还会及时更新知识点以及修正错误,阅读体验也更好。
本文地址:https://www.zhangxinxu.com/wordpress/?p=8907
(本篇完)
- 看,for..in和for..of在那里吵架! (0.298)
- 一言难尽的registerProtocolHandler()方法 (0.298)
- iframe和HTML5 blob实现JS,CSS,HTML直接当前页预览 (0.248)
- URL锚点HTML定位技术机制、应用与问题 (0.198)
- 小tips: 页面链接跳转历史URL不记录的兼容处理 (0.198)
- 借助CSS Shapes实现元素滚动自动环绕iPhone X的刘海 (0.198)
- 深度好文: 从js visibilitychange Safari下无效说开去 (0.149)
- 快速了解window.name特性与作用 (0.057)
- 如何使用JS把相对地址变成绝对地址? (0.057)
- 关于锚点跳转及jQuery下相关操作与插件 (0.050)
- 翻译 - 逐渐消失的Flash网站 (RANDOM - 0.008)
a = new URLSearchParams(‘date=2022-11-10%2C2022-11-10®ion=East+Asia&hideHeader=true&nla=0&lang=zh’);
console.log([…a.entries()])
输出是这样的:
[
[‘date’, ‘2022-11-10,2022-11-10’],
[‘region’, ‘East Asia’],
[‘hideHeader’, ‘true’],
[‘nla’, ‘0’],
[‘lang’, ‘zh’]
]
这个就很奇怪, %2C 和 + 的解析迷了
在 javascriptInfo 评论区看到一个笑话,乐了半天。
“`comments
Soldoros • 2 年前
想起了刚工作那时候用纯 JS 处理各种查询参数的痛苦
Soldoros Soldoros • 2 年前
直到今天我才知道还有 URL 这么一个对象,而且干的就是这个活儿!
JohnLee Soldoros • 1 年前
如果当时把工具库开源了说不定标准就是你来定呢233
“`
结合鑫哥说得最后一句话,确实是原生JS越来越强的情况下,有必要**温故而知新**了
嗯,感觉挺麻烦的,还是正则切割出来好啦,简单~~
在参数加密的情况下通常会带有‘+’号,而使用URL和URLSearchParams解析会丢失+号
看下来没看到有构造的url的
所以我还是喜欢node的url
啊看错了,原来开头就有…
哇,正好我可以用得上。之前自己写了一个方法从 url 里查询字段,现在方便了。谢谢张老师。
惊了,居然看到熟人了,互联网真小
跟着旭哥的步伐与时俱进。才是硬道理。学习了? 。非常感谢分享
原文这里有误:
——————————————————-
下面是带有较深层级base地址和不同相对地址形式的测试:
var base = ‘https://www.zhangxinxu.com/study/a/b/c’;
// 结果是:https://www.zhangxinxu.com/study/a/sp/icon
console.log(new URL(‘sp/icon’, base).href);
——————————————————
这个base变量的值有误,应该是var base = ‘https://www.zhangxinxu.com/study/a/b’;
那个 URL()介绍里面有笔误哦。注释写的结果和实际console.log出来的结果不同哦。
请问具体是哪一个?
原文这里有误:
——————————————————-
下面是带有较深层级base地址和不同相对地址形式的测试:
var base = ‘https://www.zhangxinxu.com/study/a/b/c’;
// 结果是:https://www.zhangxinxu.com/study/a/sp/icon
console.log(new URL(‘sp/icon’, base).href);
——————————————————
这个base变量的值有误,应该是var base = ‘https://www.zhangxinxu.com/study/a/b’;
好的,感谢反馈!
有事没事来这里逛逛,收获不少
已经习惯隔三差五 来逛逛,每次都有收获,不错
见过好多没框架就干不了活的,写个活动页面都要搬上vue全家桶?
张老师您好,我很好奇,能不能谈一谈为什么您认为「Vue和React不是未来的方向呢」?
框架只是手段,掌握好基础知识
最后一句总结真给力啊
polyfill 推荐使用corejs
鑫老师,我一直不明白,为什么很多人都抵制原生,而拥抱想JQ之类的框架。难道是因为原生的兼容性还是不够吗?
我想到的原因是,原生发展实在太慢了和太不健全了,有很大的历史局限性,而流行框架简化了原生的使用,当然应用者更多。但原生与框架都各有利弊,相辅相成,相互促进。没有必要抵制某一方,事实上,两者在发展过程中,都可能会面临一些缺少严格系统化的设计缺陷。
原生规范设计的发展慢,一是商业利益掣肘导致,二是实用至上对基础理论关心少,缺少更严谨深入的数学设计理论导致,三是软硬件工程发展变化实在太快,实验性的标准难以快速推进。
一般来讲,web语言规范,事实上都要等w3c中的浏览器及硬件大厂的代表,条件都谈妥了,才能开始标准化。当然为了保证充分的权威性、易推广性和降低应用者的学习门槛,原生语法和接口太多,反而是坏事。
因为学会框架可以直接上手干活,所以都不重视基础
工作用框架无可厚非,毕竟是做产品,需要更快有收益,但是学习可不能只盯着框架。
受教了