[筆記] JavaScript History API

YY
7 min readJan 22, 2021
Photo by Ash Edmonds on Unsplash

最近在解 bug 時翻了一些 History API 的文件,就順便記錄一下

window.history

透過 window.history 可以來控制上下頁 (back/forward) 的一些邏輯,使用 JS 來做一般的換頁或自訂的 history entry

back/forward/go

就如字面意思,history.back() 上一頁、history.forward() 下一頁,而 history.go(n) 則是往下 n 頁

history.go(1) // 下一頁,即 history.forward()
history.go(2) // 下二頁
history.go(-1) // 上一頁,即 history.back()
history.go(0) // 重整,或 history.go()

length

history.length

包含前 n 頁及後 m 頁及當前頁總共有幾個 history entry

scrollRestoration

auto

換頁時會自動記住當前的滾輪位置,跳回來時自動滾回到同個位置

history.scrollRestoration = 'auto'

manual

反之,不幫你記,換頁時捲軸一律在最上面,剩下的你自己處理

history.scrollRestoration = 'manual'

state

附加在 history entry 的資訊,一般來說會是 null,可以透過 pushState、replaceState 自行處理 history 邏輯並附帶 state

history.state

pushState

往下一頁至一個自訂的 history entry

history.pushState(stateObj, title [, url])

例如, history.pushState({ id: 'foo' }, 'title', '/foo') 就會產生一個新的 history entry 並帶有 state 為 { id: 'foo' },以及瀏覽器網址為 originalDomain.com/foo,但瀏覽器並不會去抓取 /foo 的檔案或是確認此路徑是否存在

replaceState

與 pushState 類似,但是把當前 history entry override 成自訂的 entry

history.replaceState(stateObj, title, [url])

popstate event

在 window 中有個 popstate 的 event 可以來監聽上下頁 (history entry changed)

window.addEventListener('popstate', (e) => {
console.log(e.state)
})

A popstate event is dispatched to the window every time the active history entry changes between two history entries for the same document. — MDN

要注意的是,觸發條件為按下瀏覽器的上下頁或透過 history back/forward/go 且前往的頁面是同個 document,簡單一點就是曾經有呼叫過 pushState 或 replaceState 或使用 hash anchor #

window.addEventListener('popstate', (e) => {
console.log(e.state)
})
history.pushState({ id: 1 }, '', '?foo=1')
history.pushState({ id: 2}, '', '?foo=2')
history.replaceState({ id: 3}, '')
location.href = '#foo'
history.pushState({ id: 4}, '', '?foo=4')
history.back() // popstate event fired, logs null
history.back() // popstate event fired, logs { id: 3 }
history.back() // popstate event fired, logs { id: 1}
history.back() // popstate event fired, logs null
history.back() // navigate to prev document

Use case

在這次解 bug 之旅才發現許多網站都會使用 history 來管理換頁邏輯或是塞一些頁面資訊在 history state,那透過 pushState、replaceState、popstate event 可以做哪些應用呢

在這之前可以先裝個 userscript 以更方便觀察 history state 變化以及 pushState、replaceState 被使用的情形

https://gist.github.com/x3388638/91d3b70ccc4d9419155df95b96683844

換網址

在 load more 時換網址,以便使用者複製網址或重整時回到正確位置

像是在有 infinite scroll 功能的搜尋清單透過 replaceState 來更新 URL 到相應的頁數

scroll down on 104 search result page

或是一帶多的文章頁,往下捲一捲會捲到其他篇文章,一樣透過 replaceState 來確保 URL 跟當前畫面顯示的文章相符

scroll down on Yahoo Answers QA page

SPA

利用 replaceState、pushState 記錄頁面資訊及換頁,再透過 popstate 取得 state 來做對應 history entry 的處理、render component

click repositories tab on GitHub personal page

以上記錄一下觀察到的東西,但沒什麼實際經驗也不保證內容正確,且在不同瀏覽器上的行為可能不盡相同,僅供參考

--

--