由於公司最近有個需求是想讓我們的get請求的引數都直接顯示在瀏覽器url上,這樣我們就可以直接通過複製url來顯示對應的介面資料了。
背景介紹
由於我們常用的http請求一般是基於XHR物件的實現或者fetch實現,這種請求操作並不會觸發瀏覽器url的變化,這樣雖然也能正常請求資料並渲染到頁面,但是如果使用者在當前頁面操作了某個get請求並得到了某條資料,想通過連結將當前看到的介面分享給其他人時,那麼此時瀏覽器url並不會變化,通過連結只能訪問到初始化的資料介面,此時並不能達到理想的效果。如下圖所示:
實現過程
通過以上的背景和問題,我們可以想想可以怎麼實現呢?我的第一個反應就是使用location API來實現,我們可以使用location.search來讀寫瀏覽器query引數:
location.search = '?page=2';
複製程式碼
這段程式碼雖然可以改變瀏覽器url,如下圖所示:
但會出現一個效能問題,就是當我們執行了以上程式碼後,整個瀏覽器都會重新整理,導致我們不想重新整理的部分也重新整理了,那我們有辦法可以讓它區域性重新整理嗎? 答案是必須有。這裡就要引出我們本文的重點:history API。
history API
Window.history是一個只讀屬性,用來獲取History 物件的引用,History 物件提供了操作瀏覽器會話歷史(瀏覽器位址列中訪問的頁面,以及當前頁面中通過框架載入的頁面)的介面。HTML5引入了 history.pushState() 和 history.replaceState() 方法,它們分別可以新增和修改歷史記錄條目。
使用 history.pushState() 可以改變referrer,它在使用者傳送 XMLHttpRequest 請求時在HTTP頭部使用,改變state後建立的 XMLHttpRequest 物件的referrer都會被改變。因為referrer是標識建立 XMLHttpRequest 物件時 this 所代表的window物件中document的URL。
那麼我們就可以使用pushState來實現我們的更新瀏覽器url功能了。
pushState() 方法
pushState() 需要三個引數: 一個狀態物件, 一個標題 (目前已忽略), 和 (可選的) 一個URL:
- 狀態物件 — 狀態物件state是一個JavaScript物件,通過pushState () 建立新的歷史記錄條目。無論什麼時候使用者導航到新的狀態,popstate事件就會被觸發,且該事件的state屬性包含該歷史記錄條目狀態物件的副本
- 標題 — Firefox 目前忽略這個引數,但未來可能會用到。在此處傳一個空字串應該可以安全的防範未來這個方法的更改。或者,你可以為跳轉的state傳遞一個短標題
- URL — 該引數定義了新的歷史URL記錄。注意,呼叫 pushState() 後瀏覽器並不會立即載入這個URL,但可能會在稍後某些情況下載入這個URL,比如在使用者重新開啟瀏覽器時。新URL不必須為絕對路徑。如果新URL是相對路徑,那麼它將被作為相對於當前URL處理。新URL必須與當前URL同源,否則 pushState() 會丟擲一個異常。該引數是可選的,預設為當前URL
實現
/**
* 設定瀏覽器url
* params:queryObj(引數物件)
*/
function setBrowserUrl(queryObj){
// stringify是queryString的一個api,具體可以檢視node官網,也可以自己實現
var url = `${location.pathname}?${stringify(queryObj)}`
history.pushState({url: url}, '', url)
}
複製程式碼
這樣我們就可以在請求的同時,呼叫setBrowserUrl方法來改變瀏覽器url了。 接下來我們就可以監聽瀏覽器url的變化,如果瀏覽器url有需要的請求引數,那麼我們就根據請求引數來請求資料,沒有就初始化頁面,這樣當我們檢視某條記錄或者某個小祕密時,想把該資料儲存下來並分享給被人,是不是就可以實現了呢?
總結
基於H5 history可以實現很多優雅使用的工具,比如路由,快取控制元件等等。 如果想了解更多webpack,gulp,css3,javascript,nodeJS,canvas等前端知識和實戰,歡迎在公眾號《趣談前端》加入我們一起學習討論,共同探索前端的邊界。
更多推薦
- 前端元件/庫打包利器rollup使用與配置實戰
- 一張圖教你快速玩轉vue-cli3
- vue高階進階系列——用typescript玩轉vue和vuex
- 快速掌握es6+新特性及es6核心語法盤點
- 基於nodeJS從0到1實現一個CMS全棧專案(上)
- 基於nodeJS從0到1實現一個CMS全棧專案(中)
- 基於nodeJS從0到1實現一個CMS全棧專案(下)
- 基於nodeJS從0到1實現一個CMS全棧專案的服務端啟動細節
- 使用Angular8和百度地圖api開發《旅遊清單》
- 《javascript高階程式設計》核心知識總結
- 用css3實現驚豔面試官的背景即背景動畫(高階附原始碼)
- 5分鐘教你用nodeJS手寫一個mock資料伺服器
- 教你用200行程式碼寫一個偶像拼拼樂H5小遊戲(附原始碼)