---
tags: Javascript
---
# 實作瀏覽器 URL WebAPIs
還在學習中,記錄一下在工作上遇到的問題
**需求**
* 在頁面中實踐 SPA
* 新增自訂義 query string,放到為 URL 中
* 頁面可以依據 query string 的內容去發 API
---
## 實作步驟:
瀏覽本身提供了 URL、URLSearchParams 的 WebAPIs 可以使用
參考:[URL](https://developer.mozilla.org/zh-CN/docs/Web/API/URL)、[URLSearchParams](https://developer.mozilla.org/zh-CN/docs/Web/API/URLSearchParams)
### 1. 拿取當前頁面的 URL,加入 query string
```javascript=
const currentUrl = new URL(window.location.href);
const searchParams = new URLSearchParams();
searchParams.append('item', 100);
currentUrl.search = searchParams;
const address = `http://www.test.com/page${currentUrl.search}`;
console.log(address);
// http://www.test.com/page?item=100
```
URLSearchParams 還有提供很多方法可以對參數/值做事:
```javascript
URLSearchParams.append() // 插入一個自定義的參數與值
URLSearchParams.delete() // 刪除指定參數及值
URLSearchParams.get() // 取得指定查詢的參數(第一個值)
URLSearchParams.has() // 判斷參數是否存在
```
### 2. 將自定義的 URL 加入到瀏覽器的歷史紀錄堆疊(history stack)
HTML5 提供了可以儲存網頁歷史紀錄的方法:
`history.pushState()` 和 `history.replaceState()` 方法
兩者差別在紀錄堆疊的方式不同,細節可參考:[History API](https://developer.mozilla.org/zh-TW/docs/Web/API/History_API#%E5%9C%A8%E6%AD%B7%E5%8F%B2%E7%B4%80%E9%8C%84%E4%B8%AD%E7%A7%BB%E5%8B%95)
**state**:可儲存一個 state 物件,並能在 onpopstate 事件中拿到該值
**title**:更新後頁面的標題,目前瀏覽器會忽略,文件中建議給空字串
**url**:設定要更新歷史紀錄的 URL
```javascript!
// history.pushState(state, title, url);
history.pushState(null, null, address);
```
---
## 遇到問題
被更換過的 URL 頁面,若點擊瀏覽器的上一頁按鈕卻沒有反應,但 URL 確實有被置換,查詢文件後發現,<font color="red">**瀏覽器對於新的URL並不會重新加載、檢查存在與否**</font>

## 解決方式
使用瀏覽器提供的方法 `window.onpopstate` [Window.onpopstate](https://developer.mozilla.org/zh-TW/docs/Web/API/Window/popstate_event)
該方法會在會在歷史紀錄有發生變動時被觸發(例如點擊瀏覽器的上下一頁按鈕)一個 popstate event
我們就可以在事件中,加入自定義的內容,去判斷當前狀態是否需要進行頁面重載
```javascript!
window.onpopstate = function(event) {
if (event.state) return
location.reload();
}
```

## 參考相關資料
* [操控瀏覽器歷史紀錄](https://developer.mozilla.org/zh-TW/docs/Web/API/History_API#%E5%9C%A8%E6%AD%B7%E5%8F%B2%E7%B4%80%E9%8C%84%E4%B8%AD%E7%A7%BB%E5%8B%95)
* [瀏覽器的時光機—歷史堆疊、 pushState 與 replaceState API](https://medium.com/%E5%89%8D%E7%AB%AF%E5%AF%A6%E5%8A%9B%E4%B8%89%E6%98%8E%E6%B2%BB/%E7%80%8F%E8%A6%BD%E5%99%A8%E7%9A%84%E6%99%82%E5%85%89%E6%A9%9F-pushstate-replacestate-api-fa1d909c82b0)
* [history.pushState - not working?](https://stackoverflow.com/questions/14824766/history-pushstate-not-working)