每日 30 秒 ⏱ URL 大爆炸

封面

簡介

URL結構、組成、query、hash、axios數組傳遞錯誤、HTTP 請求

伴隨着微信消息的提示音 小四 發來一段代碼說 不知道爲何請求不到頁面數據javascript

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

小二一看大機率是 query數組傳遞方式引發的,因爲後端實現解析數組 ids:[5, 6, 100] 可能有如下幾種方式:html

  • 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 直接代碼一試沒報錯能運行,無論它的原理是什麼,如今想一想挺可怕的。前端

雖然每天和 URL 打交道但並非全部人都懂它。

對於爲何代碼能運行也不是全部人都會去深究它html5

現原形

利用 URL() 對象能夠快速的把一個 url地址 打回原形:java

腳本
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地址 裏面竟然有這麼多屬性,在這裏主要會講解的 hashsearchios

推薦打開控制檯把腳本運行一下,這樣閱讀的時候就不須要上下對照查看了。

host 和 hostname

眼尖的同窗確定發現了 hosthostname 竟然如出一轍這是爲何呢?git

回憶一下開發常常在見到的 localhost:8080,這裏出現了端口號 8080 而平時使用訪問一些網站的時候卻沒有帶上端口號。這是由於 url地址 會默認端口號爲 80,因此你仔細看看會發現上面 port 的值爲空。github

hosthostname 的區別即是有 port 的時候 host 會包含端口號,而 hostname 不會包含。npm

protocol 和 origin

protocol 指的即是 協議 最多見的有 httphttps,固然如今瀏覽器再不輸入協議時會自動幫你加上,不過在 URL() 不帶上協議但是會報錯的哦。origin 則爲 protocelhost 拼接組成。json

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
相關文章
相關標籤/搜索