前言
URL
對於我們開發人員來講,應該是非常熟悉了。在對URL
進行引數拼接時,我們一般都會直接進行字串拼接或使用模版字串,因為這樣非常方便,但是我們這樣其實會在不知不覺中以不安全的方式編寫 URL。
比如,我們通常會這樣寫:
const url = `https://www.baidu.com
?model=${model}&locale=${locale}?query.text=${text}`
這樣確實寫起來非常方便,但你可能會在不知不覺中會你的程式帶來一些問題。(如上程式碼就是一段有問題的程式碼)
如果這篇文章有幫助到你,❤️關注+點贊❤️鼓勵一下作者,文章公眾號首發,關注 前端南玖
第一時間獲取最新文章~
常見問題
不正確的分隔符
這種錯誤可能在新手身上比較常見,但即使是經驗老道的程式設計師也不可能絕對避免這個錯誤。造成這個錯誤的罪魁禍首絕大多數是在修改或移動程式碼之後。例如,你有一個結構正確的 URL,然後將一個片段從一個片段複製到另一個片段,然後錯過了引數分隔符的錯誤排序。
忘記編碼
許多時候我們URL
上的引數是需要進行編碼的,因為URL
引數可以是任意型別的文字,包括空格和特殊字元,這會給我們帶來一些無法預料的問題。
所以為了避免這種情況,我們往往會這樣寫:
const url = `https://www.baidu.com
?model=${
encodeURIComponent(model)
}&locale=${
encodeURIComponent(locale)
}&query.text=${
encodeURIComponent(text)
}`
但這樣的寫法給人的感覺是非常的冗餘且不雅觀?
意外的空白字元
有時候我們為了將一個長 URL
分成多行,我們會不小心在 URL 中包含了換行符和額外的空格,這將導致無法按預期進行抓取。
所以為了正確分解URL
字串,我們通常會這樣寫:
const url = `https://www.baidu.com`
+ `?model=${
encodeURIComponent(model)
}&locale=${
encodeURIComponent(locale)
}&query.text=${
encodeURIComponent(text)
}`
但這樣是我們的程式碼變得更加混亂以及難以閱讀。
難道就沒有一種既安全又優雅的方法來編寫URL
嗎??
URL建構函式
既優雅又安全的方法就是使用URL
建構函式
URL()
建構函式返回一個新建立的URL
物件,表示由一組引數定義的 URL。如果給定的基本 URL 或生成的 URL 不是有效的 URL 連結,則會丟擲一個
TypeError
。
語法
const url = new URL(url [, base])
引數
-
url
是一個表示絕對或相對 URL 的
DOMString
。如果url
是相對 URL,則會將base
用作基準 URL。如果url
是絕對 URL,則無論引數base
是否存在,都將被忽略 -
base
可選是一個表示基準 URL 的
DOMString
,在 url 是相對 URL 時,它才會起效。如果未指定,則預設為''
解決
所以上面的URL
我們就可以這樣來寫:
const url = new URL('https://www.baidu.com')
url.searchParams.set('model', model)
url.searchParams.set('locale', locale)
url.searchParams.set('text', text)
這樣寫就可以為我們解決這些問題:
- 分隔符總是正確的(
?
對於第一個引數,以及之後的引數) - 所有引數都自動編碼
- 長 URL 跨多行時沒有額外空白字元的風險
修改URL
對於我們在不知道當前引數狀態下的情況,它也非常適用。
比如:
url += (url.includes('?') ? '&' : '?') + 'foo=bar'
使用URL
建構函式我們可以這樣寫:
// url是一個URL建構函式
url.searchParams.set('foo', 'bar')
// 或者是一個字串
const structuredUrl = new URL(url)
structuredUrl.searchParams.set('foo', 'bar')
url = structuredUrl.toString()
讀取URL
現在,我如果想在沒有庫的情況下從當前 URL 讀取查詢引數這個由來已久的問題也得到了解決。
const pageParam = new URL(location.href).searchParams.get('page')
const url = new URL(location.href)
const currentPage = Number(url.searchParams.get('page'))
url.searchParams.set('page', String(currentPage + 1))
location.href = url.toString()
這不僅限於瀏覽器,它也可以在 Node.js 中使用
const http = require('http');
const server = http.createServer((req, res) => {
const url = new URL(req.url, `https://${req.headers.host}`)
});
URL屬性
URL 例項支援您已經在瀏覽器中使用的所有屬性,例如 onwindow.location
或 anchor 元素,所有這些我們都可以讀寫:
const url = new URL('https://www.baidu.com/a?page=1');
url.protocol // https:
url.host // www.baidu.com
url.pathname // /a
url.search // ?page=1
url.href // https://www.baidu.com/a?page=1
url.origin // https://www.baidu.com
url.searchParams.get('page') // 1
常用URLSearchParams方法
該URLSearchParams
物件可在URL
例項上訪問,url.searchParams
支援許多方便的方法:
searchParams.has(name)
檢查搜尋引數是否包含給定名稱
url.searchParams.has('page') // true
searchParams.get(name)
獲取給定引數的值
url.searchParams.get('page') // '1'
searchParams.getAll(name)
獲取為引數提供的所有值。如果你允許同名的多個值,這很方便,例如
&page=1&page=2
url.searchParams.getAll('page') // ['1']
searchParams.set(name, value)
設定引數的值
url.searchParams.set('page', '1')
searchParams.append(name, value)
附加一個引數——如果你可能多次支援同一個引數,這很有用,比如
&page=1&page=2
url.searchParams.append('page', '2')
searchParams.delete(name)
從 URL 中完全刪除一個引數
url.searchParams.delete('page')
相容性
new URL
基本支援所有現代瀏覽器(除了IE),以及 Node.js。