為什么要URL編碼?
在因特網(wǎng)上傳送URL,只能采用ASCII字符集
也就是說URL只能使用英文字母、阿拉伯?dāng)?shù)字和某些標(biāo)點(diǎn)符號(hào),不能使用其他文字和符號(hào),即
只有字母和數(shù)字[0-9a-zA-Z]、一些特殊符號(hào)$-_.+!*()、以及某些保留字(空格轉(zhuǎn)換為+)才可以不經(jīng)過編碼直接用于URL
這意味著 如果URL中有漢字,就必須編碼后使用
但是麻煩的是 標(biāo)準(zhǔn)的國際組織并沒有規(guī)定具體的編碼方法,而是交給應(yīng)用程序(瀏覽器)自己決定。 這導(dǎo)致"URL編碼"成為了一個(gè)混亂的領(lǐng)域。
如果包含中文,其實(shí)會(huì)自動(dòng)編碼的,比如Chrome和火狐,"文"和"章"的utf-8編碼分別是"E6 96 87"和"E7 AB A0" ,下圖所示的"%e6%96%87%e7%ab%a0"就是按照順序,在每個(gè)字節(jié)前加上%而得到的:

但是不同的瀏覽器可能會(huì)有不同的編碼方式,不要將編碼交給瀏覽器。應(yīng)該用JS在前端對(duì)URL編碼,這樣就實(shí)現(xiàn)了統(tǒng)一
如何編碼?
URL編碼通常也被稱為百分號(hào)編碼(percent-encoding),是因?yàn)樗木幋a方式非常簡單:
使用%加上兩位的字符——0123456789ABCDEF——代表一個(gè)字節(jié)的十六進(jìn)制形式。URL編碼要做的,就是將每一個(gè)非安全的ASCII字符都被替換為“%xx”格式,
對(duì)于非ASCII字符,RFC文檔建議使用utf-8對(duì)其進(jìn)行編碼得到相應(yīng)的字節(jié),然后對(duì)每個(gè)字節(jié)執(zhí)行百分號(hào)編碼。
如"中文"使用UTF-8字符集得到的字節(jié)為0xE4 0xB8 0xAD 0xE6 0x96 0x87,經(jīng)過Url編碼之后得到"%E4%B8%AD%E6%96%87"。
一些常見的特殊字符換成相應(yīng)的十六進(jìn)制的值:
+ %20
/ %2F
? %3F
% %25
# %23
& %26
假如我們有一個(gè)需要編碼的url:
var url = 'http://www.baidu.com?name=李曉韜&age=2'
現(xiàn)在分別用escape、encodeURI、encodeURIComponent 這三種方式編碼
escape(url) // http%3A//www.baidu.com%3Fname%3D%u674E%u6653%u97EC%26age%3D2
encodeURI(url) // http://www.baidu.com?name=%E6%9D%8E%E6%99%93%E9%9F%AC&age=2
encodeURIComponent(url) // http%3A%2F%2Fwww.baidu.com%3Fname%3D%E6%9D%8E%E6%99%93%E9%9F%AC%26age%3D2
漢字都被編碼了,貌似都沒問題,但是如果我們需要在瀏覽器中打開編碼后的url就有問題了,只有用encodeURI編碼的url可以在瀏覽器中打開
所以如果我們有這樣一個(gè)需求:
- 接口傳給我們一個(gè)帶漢字的url
- 拿到url后要用瀏覽器打開,如果有漢字在瀏覽器中打開可能會(huì)報(bào)錯(cuò),需要編碼
滿足以上兩個(gè)條件就必須用encodeURI編碼
以下是對(duì)這三種編碼方式的介紹:
只有 0-9[a-Z] $ - _ . + ! * ' ( ) , 以及某些保留字,才能不經(jīng)過編碼直接用于 URL
escape 和 unescape
原理:對(duì)除ASCII字母、數(shù)字、標(biāo)點(diǎn)符號(hào) @ * _ + - . / 以外的其他字符進(jìn)行編碼。
編碼:escape('http://www.baidu.com?name=zhang@xiao@jie&order=1')
結(jié)果:"http%3A//www.baidu.com%3Fname%3Dzhang@xiao@jie%26order%3D1"
編碼:escape('張')
結(jié)果:"%u5F20"
解碼:unescape("http%3A//www.baidu.com%3Fname%3Dzhang@xiao@jie%26order%3D1")
結(jié)果:"http://www.baidu.com?name=zhang@xiao@jie&order=1"
解碼:unescape("%u5F20")
結(jié)果:"張"encodeURI 和 decodeURI (推薦使用)
原理:返回編碼為有效的統(tǒng)一資源標(biāo)識(shí)符 (URI) 的字符串,不會(huì)被編碼的字符:! @ # $ & * ( ) = : / ; ? + '
encodeURI()是Javascript中真正用來對(duì)URL編碼的函數(shù)。
用于:對(duì)整個(gè)url進(jìn)行編碼
編碼:encodeURI('http://www.baidu.com?name=zhang@xiao@jie&order=1')
結(jié)果:"http://www.baidu.com?name=zhang@xiao@jie&order=1"
解碼:decodeURI("http%3A//www.baidu.com%3Fname%3Dzhang@xiao@jie%26order%3D1")
結(jié)果:"http%3A//www.baidu.com%3Fname%3Dzhang@xiao@jie%26order%3D1"encodeURIComponent 和 decodeURIComponent
原理:對(duì)URL的組成部分進(jìn)行個(gè)別編碼,而不用于對(duì)整個(gè)URL進(jìn)行編碼
用于:對(duì)url上的參數(shù)編碼
function param (data) {
let url = ''
for (var k in data) {
let value = data[k] !== undefined ? data[k] : ''
url += '&' + k + '=' + encodeURIComponent(value)
}
return url ? url.substring(1) : ''
}
編碼:encodeURIComponent('http://www.baidu.com?name=zhang@xiao@jie&order=1')
結(jié)果:"http%3A%2F%2Fwww.baidu.com%3Fname%3Dzhang%40xiao%40jie%26order%3D1"
解碼:decodeURIComponent("http%3A%2F%2Fwww.baidu.com%3Fname%3Dzhang%40xiao%40jie%26order%3D1")
結(jié)果:"http://www.baidu.com?name=zhang@xiao@jie&order=1"