環境
main @ 0c327f7,courses/gym,Chromium 141.0.7390.37 headless,1280×900。
現象
在站內切了幾個分頁之後按「上一頁」,不會回到前一個分頁,而是直接離開網站。
手機上尤其明顯,返回鍵是主要導航手段。
另外網址列永遠停在原本的 URL,所以也沒辦法把「現在看的這個分頁」分享出去。
重現與實測
| 步驟 |
body[data-tab] |
網址列 query |
| 進站 |
home |
(無) |
| 點「課程」 |
course |
(無) |
| 點「上課」 |
player |
(無) |
| 按上一頁 |
— |
about:blank(已離站) |
根因
setTab()(app.js:254)只寫 localStorage 與 document.body.dataset,
整份 src/web/js/ 沒有任何 history.pushState / replaceState / popstate
(grep -rn "history\.\|popstate" src/web/js/ 零命中)。
值得一提的是這裡是不對稱的:init()(app.js:755-761)會讀 ?tab= 決定初始分頁,
所以分頁本來就被設計成可以放進網址的狀態,只是從來沒有被寫回去。
我的修法
setTab() 加一個 fromHistory 參數,非歷史還原時 pushState;
init() 用 replaceState 定初始狀態(初始分頁不該疊一筆歷史),再掛 popstate 還原:
function setTab(tab, fromHistory = false) { if (!fromHistory) { const url = new URL(location); url.searchParams.set("tab", tab); if (history.state?.tab !== tab) history.pushState({ tab }, "", url); } …}// init()history.replaceState({ tab: initialTab }, "", location);setTab(initialTab, true);window.addEventListener("popstate", (e) => { const t = e.state?.tab || new URLSearchParams(location.search).get("tab") || "home"; setTab(["home", "course", "player", "stance"].includes(t) ? t : "home", true);});
環境
main@0c327f7,courses/gym,Chromium 141.0.7390.37 headless,1280×900。現象
在站內切了幾個分頁之後按「上一頁」,不會回到前一個分頁,而是直接離開網站。
手機上尤其明顯,返回鍵是主要導航手段。
另外網址列永遠停在原本的 URL,所以也沒辦法把「現在看的這個分頁」分享出去。
重現與實測
根因
setTab()(app.js:254)只寫localStorage與document.body.dataset, 整份src/web/js/沒有任何history.pushState/replaceState/popstate(grep -rn "history\.\|popstate" src/web/js/零命中)。值得一提的是這裡是不對稱的:
init()(app.js:755-761)會讀?tab=決定初始分頁, 所以分頁本來就被設計成可以放進網址的狀態,只是從來沒有被寫回去。我的修法
setTab()加一個fromHistory參數,非歷史還原時pushState;init()用replaceState定初始狀態(初始分頁不該疊一筆歷史),再掛popstate還原: