該系列主要圍繞前端一些基礎性的內容進行回顧整理,為日益紛繁的各類框架打下一個基礎的底子,便於理解一些框架內容。
今天我們主要來回顧一下有關於URI
和URL
相關的內容。
URI是什麼
統一資源識別符號(Uniform Resource Identifier,URI
),允許使用者對網路中的資源通過特定的協議進行互動操作。RFC2396
文件對Uniform Resource Identifier
各部分的定義如下。
Uniform
:規定統一的語法格式,以方便處理多種不同型別的資源,而無須根據上下文環境來識別資源型別。Resource
:可標識的任何資源。資源不僅可以為單一物件,也可以為多個物件的集合體。Identifier
:表示可標識的物件,也稱為識別符號。
在一般情況下,URI
為由某個協議方案表示的資源的定位識別符號。協議方案是指訪問資源時所使用的協議型別名稱。HTTP
就是協議方案的一種,除此之外,還有FTP
、file
、TELNET
等30種標準URI協議方案。協議方案由網際網路號碼分配局(IANA)管理頒佈。URI使用字串標識某一網際網路資源,常用的URL
作為URI
的子集,表示某一網際網路資源的地點。
URI
的通用語法由5個元件組成:
URI = scheme:[//authority]path[?query][#fragment]
在URI語法中:
scheme
為協議方案名,在使用HTTPS
或HTTP
等協議方案名時不區分大小寫,最後一個符號為冒號“:”。協議方案名也可使用javascript:、data:
指定指令碼程式或資料。path
為帶層次的檔案路徑,指定伺服器上的檔案路徑,以訪問特定的資源。query
為查詢字串,針對指定路徑的檔案資源,可使用查詢字串傳入任意查詢引數。fragment
為片段識別符號,通常標記已獲取資源的子資源,為可選項。authority
可以由以下3分佈組成:
authority = [userinfo@]host[:port]
在authority
中,userinfo
作為登入資訊,通常形式為指定使用者名稱和密碼,當從伺服器獲取資源時作為身份認證憑證使用。userinfo
為可選項。伺服器地址host
在使用絕對路徑URI
時需指定訪問的伺服器地址,地址可以為被DNS
解析的域名,如example.com
,或者192.168.1.1
的IPv4地址及用方括號括起來的IPv6地址[0:0:0:0:0:0:0:1]
。port
為伺服器連線的網路埠號,作為可選項,如果不指定,則自動使用預設的埠號。
URL是什麼
統一資源定位器(UniformResourceLocators,URL
)作為URI的一種,如同網路的門牌,標識了一個網際網路資源的“住址”,如<http://www.example.com>
表示通過HTTP協議從主機名為www.example.com
的主機上獲取首頁資源。
URL
的語法定義與URI
是一致的,它屬於URI
的一個子集。
統一資源名稱(Uniform Resource Name
)也是標準格式的URI
,指的是資源而不指定其位置或是否存在。鑑於該概念在日常前端的範圍內接觸較少,僅作為了解即可,有興趣的可以自行查閱相關內容。
URI和URL的關係是什麼呢
統一資源名稱(Uniform Resource Name)也是標準格式的URI,指的是資源而不指定其位置或是否存在。鑑於該概念在日常前端的範圍內接觸較少,僅作為了解即可,有興趣的可以自行查閱相關內容。
借用一張圖來理解他們之間的關係:URI可以分為URL,URN或同時具備locators 和names特性的一個東西。URN作用就好像一個人的名字,URL就像一個人的地址。換句話說:URN確定了東西的身份,URL提供了找到它的方式。
大白話來說,就是URI
是抽象的定義,不管用什麼方法表示,只要能定位一個資源,就叫URI
。本來設想的的使用兩種方法定位:1、URL
,用地址定位;2、URN
用名稱定位。
舉個例子:去村子找個具體的人(URI
),如果用地址:某村多少號房子第幾間房的主人-就是URL
; 如果用身份證號+名字去找-就是URN
了。
瀏覽器URI編碼
URI
編碼使用的是百分號編碼(Percent-encoding
)。對於需要編碼的字元,將其表示為兩個十六進位制的數字,然後在其前面放置轉義字元“%”
,並替換原字元相應位置進行編碼。
URI
中只允許包含未保留字元及所有保留字元。其中,未保留字元包含英文字母(a~z,A~Z),數字(0~9),-、_、.、~4個特殊字元
,共66個。對於未保留字元,不需要進行百分號編碼。保留字元是那些具有特殊含義的字元。RFC 3986
文件中規定了18個保留字元:
!*'();:@&=+$,/?#[]
在URI
中,保留字元有特殊的意義,如“?”表示查詢,“#”表示片段標識。如果希望保留字元不表示特定的意義,僅表示一般字元,那麼需要對保留字元進行URL編碼。常用的編碼方法主要有encodeURI
和encodeURIComponent
。
encodeURI和encodeURIComponent
encodeURI()
和encodeURIComponent()
都是Javascript中對URL編碼的函式。
區別在於:
encodeURI
是W3C
的標準(RFC 3986
),不對ASCII字母和數字
進行編碼,不對20個ASCII標點符號(-、_、.、!、~、*、'、(、)、;、/、?、:、@、&、=、+、$、,、#)
進行編碼。對於66個未保留字元,18個保留字元
,除去2個不安全的保留字元“[”“]”
,encodeURI
的不編碼集為82
個。對於非ASCII字元,encodeURI
需要將其轉換為UTF-8
編碼位元組序,然後在每個位元組前面放置轉義字元(%)進行百分號編碼,並置入URI中的相應位置。UTF-8:UTF-8具有無位元組序要求、單位元組特性節約記憶體、向後相容ASCII、錯誤相容性好等優點。一個純ASCII字串也是一個合法的UTF-8字串,所以現存的ASCII文字不需要轉換。為傳統的擴充套件ASCII字符集設計的軟體通常可以不經修改或經過很少修改就能與UTF-8一起使用。
encodeURIComponent
假定引數是URI
的一部分(比如協議、主機名、路徑或查詢字串),因此,encodeURIComponent
將轉義除字母、數字、“(”、“)”、“.”、“!”、“~”、“*”、“'”、“-”和“_”
外的所有字元。例如,對“name=val&key=”
進行encodeURIComponent
編碼後結果為“"name%3Dval%26key%3D"”
。對於URL
組成部分中的特殊字元,通常需要使用encodeURIComponent
進行編碼,如:name=encodeURIComponent('val&key=') // name=val%26key%3D
相比encodeURIComponent
,encodeURI
被用作對一個完整的URI
進行編碼,而encodeURIComponent
則被用作對URI
的一個元件或者URI
中的一個片段進行編碼。從上面的編碼示例來看,encodeURIComponent
編碼的字元範圍要比encodeURI
大。
小結
以上就是針對URI
和URL
以及相關編碼方法的回顧梳理。在日常的前端開發中,URL
等概念是我們經常提及的,而相關的編碼轉碼方法也在我們的日常開發中經常會用到。希望本次回顧也能夠幫助大家重溫加深一下這些知識。
參考資料
-《深入理解React Router從原理到實戰》