每日 30 秒 ⏱ URL 大爆炸

简介

URL结构、组成、query、hash、axios数组传递错误、HTTP 请求javascript

伴随着微信消息的提示音 小四 发来一段代码说 不知道为何请求不到页面数据html

axios.get('users', {
    params: { ids: [1, 2, 3] }
})
复制代码

小二一看大几率是 query数组传递方式引发的,因为后端实现解析数组 ids:[5, 6, 100] 可能有如下几种方式:前端

  • bracket: ids[]=1&ids[]=2&ids[]=3
  • index: ids[0]=1&ids[1]=2&ids[3]=3
  • comma: ids=1,2,3
  • none: ids=1&ids=2&ids=3

小四分别测试后便把问题解决了,这也让小二想起 小熊猫哥哥 在开发的时候,也遇到过这个问题网上一搜发现别人用 qs 库中的 stringify 直接代码一试没报错能运行,无论它的原理是什么,如今想一想挺可怕的。html5

虽然每天和 URL 打交道但并非全部人都懂它。java

对于为何代码能运行也不是全部人都会去深究它ios

现原形

利用 URL() 对象能够快速的把一个 url地址 打回原形:git

脚本
const url = new URL('http://www.pushme.top/users?sort_by=asc#page=userlist')
console.log(url)
复制代码
输出
{
    hash: "#page=userlist"
    host: "www.pushme.top"
    hostname: "www.pushme.top"
    href: "http://www.pushme.top/users?sort_by=asc#page=userlist"
    origin: "http://www.pushme.top"
    password: ""
    pathname: "/users"
    port: ""
    protocol: "http:"
    search: "?sort_by=asc"
    searchParams: URLSearchParams {}
    username: ""
}
复制代码

没想到吧 小小的一段 url地址 里面竟然有这么多属性,在这里主要会讲解的 hashsearchgithub

推荐打开控制台把脚本运行一下,这样阅读的时候就不须要上下对照查看了。npm

host 和 hostname

眼尖的同窗确定发现了 hosthostname 竟然如出一辙这是为何呢?json

回忆一下开发常常在见到的 localhost:8080,这里出现了端口号 8080 而平时使用访问一些网站的时候却没有带上端口号。这是由于 url地址 会默认端口号为 80,因此你仔细看看会发现上面 port 的值为空。

hosthostname 的区别即是有 port 的时候 host 会包含端口号,而 hostname 不会包含。

protocol 和 origin

protocol 指的即是 协议 最多见的有 httphttps,固然如今浏览器再不输入协议时会自动帮你加上,不过在 URL() 不带上协议但是会报错的哦。origin 则为 protocelhost 拼接组成。

search 和 searchParams

基础

?search=aquery 以第一个?开始至行尾#结束。用于向后端传递一些数据,数据使用 & 进行分隔,值使用 = 分隔。经过一段代码来理解一下:

const query = 'id=1&sort=asc&hello=world';
// 对 & 分割取得数据对
const data = query.split('&').reduce((data,keyValue) => {
    const [ key, value ] = keyValue.split('=');
    return (data[key] = value, data);
}, {});

// 输出 {id: "1", sort: "asc", hello: "world"}
console.log(data);
复制代码

这就是 query 最基础的数据对的组合方式,固然开头的四种 数组 的表达方式须要进行另外的处理,无外乎就是对 key 的收集 和 value 的判断。不过这部分基本上后端的框架都帮咱们处理好了,前端也可使用 qsquery-stringqss 等库来完成。

题外话:这几个库代码都挺少的,值得一读说不定有新收获。

加号与空格

天天使用的 百度谷歌 中不知道你们有没有主要到这几个细节:

  • 输入 https://www.baidu.com/s?wd=小二+pushmetop 搜索框中出现的是小二 pushmetop,地址栏中url地址的 + 神奇的变成了 空格
  • 输入 https://www.baidu.com/s?wd=小二 pushmetop 搜索框中出现的是小二 pushmetop,地址栏中url地址的 空格 的变成 %20
  • 输入 https://www.baidu.com/s?wd=小二%2Bpushmetop 搜索框中出现的是小二+pushmetop,地址栏中url地址的 %2B 的变成 +

具体缘由能够查看 维基百科 关于 保留字符的百分号编码

URL 编码

掘金 等网站点击连接都会快速的闪现相似 http://www.pushmetop.com?redirect=xxxxxurl地址,会发现 redirect 对应的重定向地址会是一堆夹带 % 的乱码这是为何呢?

让咱们假设须要跳转的连接是 www.test.com?hello=world&id=1,把整个连接拼接起来则为:

http://www.pushmetop.com?redirect=www.test.com?hello=world&id=1
复制代码

根据一开始的定义 解析值预期值 彻底不一样了:

解析值
{
    "redirect": "www.test.com?hello=world",
    "id": "1"
}
复制代码
预期值
{
    "redirect": "www.test.com?hello=world&id=1"
}
复制代码

为了解决这个问题便诞生了 URL编码 来解决问题:

  • encodeURIComponent()decodeURIComponent() 推荐使用。
  • encodeURI()decodeURI() 对比前者不会对 "; / ? : @ & = + $ , #" 这些字符编码。
  • escape()unescape() 不推荐使用。
例子
let redirect = 'www.test.com?hello=world&id=1';
redirect = encodeURIComponent(redirect);

let url = `http://www.pushmetop.com?redirect=${redirect}`;
url = new URL(url)

// 输出: www.test.com?hello=world&id=1
console.log(url.searchParams.get('redirect'))
复制代码

hash

#hashfragment# 为开始 行尾 为结束。在 回到顶部 中有提到过利用hash锚点来进行跳转,若是你们注意观察的话会发现 hash 的改变不会引发页面的刷新。

Angular.jsVue Router 等库中,会利用在 html5 中提供了 history 的一系列操做,来帮助咱们不刷新页面管理 url。可是在一些旧的浏览器上并不兼容时,会利用 hash 不会主动触发浏览器 reload 的特性来修改 location.hash 来管理路由。 固然 hash 的另一个特色是能够被保存为书签。

hash 的小妙用也能够像 query 那样利用 &= 来存取数据,固然你也能够定制属于你的规则。

href 和 pathname

href 为整个 url地址。而 pathname 属性包含 URL 的整个路径部分。它跟在 host (包括 port)后面,排在 queryhash 组成部分的前面且被 ASCII 问号(?)或哈希字符(#)分隔。

username 和 password

usernamepassword 在平常使用中不多用,它们能够合称为 auth。该字符串跟在 protocol 和双斜杠(若是有)的后面,排在 host 部分的前面且被一个 ASCII 的 at 符号(@)分隔:

http://username:password@www.pushme.top/test/blah?something=123
复制代码

结尾

原本只是想讨论 hashsearch ,结果全都过一遍,今天就辛苦你们了。

一块儿成长

在困惑的城市里总少不了并肩同行的 伙伴 让咱们一块儿成长。

  • 若是您想让更多人看到文章能够点个 点赞
  • 若是您想激励小二能够到 Github 给个 小星星
  • 若是您想与小二更多交流添加微信 m353839115

微信公众号

本文原稿来自 PushMeTop