什么是 URI?URI 和 URL 的区别是?URI 的编码方法?
如果不知道的话就往下看看吧~
什么是 URI
URI (Uniform Resource Identifier),也就是 统一资源标识符 。
它的 作用 就是区分互联网上不同的资源。
URI 包括两个部分:
- URL (Uniform Resource Location),统一资源定位符 。
- URN (Uniform Resource Name),统一资源名称 。
URI 的 结构:
scheme :// user:passwd @ host:port path ? query #fragment
scheme 表示协议名,比如 http , https , file 等等。后面必须和 ://连在一起。协议可以自定义。
user:passwd@ 表示登陆主机时的用户名和密码,不过很不安全,不推荐使用,也不常用。
host:port 表示主机名和端口。
path 表示请求路径,标记资源所在位置。
query 表示查询参数 ,以? 开始,为 key = val 键值对的形式 ,以 & 隔开。
fragment 也叫哈希。表示 URI 所定位的资源内的一个锚点,浏览器可以根据这个锚点跳转到对应位置。
例子:
https://www.baidu.com/s?wd=HTTP&rsv_spt=1#heading-8复制代码
https 即 scheme 协议
www.baidu.com 即 host:port 主机名和端口。注意,http 和 https 的默认端口分别是80、443。
/s 即 path 请求路径,标记资源所在位置。
wd=HTTP&rsv_spt=1 即 query 参数部分,且为两个。
heading-8 即 fragment 锚点。
URL 为 https://www.baidu.com/s?wd=HTTP&rsv_spt=1
URN 为 www.baidu.com/s?wd=HTTP&rsv_spt=1#heading-8
URI 编码方法
URI 只能使用ASCII, ASCII 之外的字符是不支持显示的,而且还有一部分符号是界定符,如果不加以处理就会导致解析出错。
因此,URI 引入了 编码机制 ,将所有非 ASCII 码字符和界定符转为十六进制字节值,然后在前面加个%。
如,空格被转义成了%20,布纳纳被转义成了 %E5%B8%83%E7%BA%B3%E7%BA%B3。
encodeURI() 和 encodeURIComponent()
encodeURI() 和 encodeURIComponent() 方法用于编码统一资源标识符(URI),以便传给浏览器。
- encodeURI()方法用于对整个 URI 进行编码
- encodeURIComponent() 方法用于编码 URI 中单独的组件,
let uri = "https://zhuanlan.zhihu.com/p/40311981?redirect=a"console.log(encodeURI(uri))// https://zhuanlan.zhihu.com/p/40311981?redirect=a// 使用 encodeURI()编码后,除空格被替换为%20 之外,没有任何变化。console.log(encodeURIComponent(uri))// https%3A%2F%2Fzhuanlan.zhihu.com%2Fp%2F40311981%3Fredirect%3Da// encodeURIComponent()方法将所有非字母字符都替换成了相应的编码形式。复制代码
因此,我们发现这两个方法的 主要区别 是:encodeURI() 不会编码属于 URL 组件的特殊字符,比如冒号、斜杠、问号、 井号,而 encodeURIComponent() 会编码它发现的所有非标准字符。这就是使用 encodeURI() 编码整个 URI,但只使用 encodeURIComponent() 编码那些会追加到已有 URI 后面的字符串的原因。
注意 一般来说,使用 encodeURIComponent() 比使用 encodeURI() 的频率更高, 这是因为编码查询字符串参数比编码基准 URI 的次数更多。
decodeURI() 和 decodeURIComponent()
decodeURI() 只对使用 encodeURI() 编码过的 字符解码。
同样,decodeURIComponent() 只对使用 encodeURIComponent() 编码过的字符解码 ,基本上就是解码所有特殊值。
例子:
let uri = "http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.js%23start";console.log(decodeURI(uri));// http%3A%2F%2Fwww.wrox.com%2Fillegal value.js%23startconsole.log(decodeURIComponent(uri)); // http:// www.wrox.com/illegal value.js#start复制代码
这里,uri 变量中包含一个使用 encodeURIComponent()编码过的字符串。
首先输出的是使用 decodeURI() 解码的结果,可以看到只用空格替换了%20 。
然后是使用 decodeURIComponent() 解码的 结果,其中替换了所有特殊字符,并输出了没有包含任何转义的字符串。(这个字符串不是有效的 URL。)
如何获取 URI 参数?
// 1.取 ? 开头,# 结尾 的字符串// 2.根据 & 分割参数// 3.根据 = 分割键值对function getParams(str){ // ? 的索引 const startIdx = str.indexOf('?') + 1; const endIdx = str.indexOf('#') const paramString = str.substring(startIdx ,endIdx); console.log('paramString:' + paramString) const kvArr = paramString.split('&'); console.log('kvArr:' + kvArr) const params = {}; kvArr.forEach(item =>{const [k,v] = item.split('='); params[k] = v; }); return params; }console.log(getParams('https://zhuanlan.zhihu.com/p/40311981?redirect=a¶m=b#heading-8'));复制代码
https://zhuanlan.zhihu.com/p/40311981?redirect=https://www.baidu.com?a=10¶m=b#heading-8 的参数是?
console.log(getParams('https://zhuanlan.zhihu.com/p/40311981?redirect=https://www.baidu.com?a=10¶m=b#heading-8'));// {redirect: "https://www.baidu.com?a", param: "b"}复制代码
这明显不对, redirect 的值应该是 https://www.baidu.com?a=10 。解决:
let redirect = "https://www.baidu.com?a"let uri = `https://zhuanlan.zhihu.com/p/40311981?redirect=${encodeURIComponent(redirect)}¶m=b#heading-8`console.log(getParams(uri))复制代码
如果想让参数只有 redirect 且值是 https://www.baidu.com?a=10¶m=b呢?
let redirect1 = "https://www.baidu.com?a=10¶m=b"let uri1 = `https://zhuanlan.zhihu.com/p/40311981?redirect=${encodeURIComponent(redirect1)}#heading-8`console.log(getParams(uri1))复制代码
最后
如有问题请大佬指正~
如有帮助,希望能够点赞收藏~