popstate イベント検知 — window.addEventListener('popstate', ()=>{})
popstate イベントは ブラウザの「戻る」「進む」操作や history.back() / history.forward() が呼ばれたときに発火します。history.pushState や history.replaceState で履歴に状態オブジェクトを保存しておくと、その状態を event.state から取り出して画面を復元できます。SPA(シングルページアプリケーション)や検索条件の保持に必須の仕組みです。
基本のコード例
<button id="next">次へ</button>
<div id="content">初期ページ</div>
<script>
const content = document.getElementById("content");
let page = 1;
// 「次へ」ボタンで履歴を積む
document.getElementById("next").addEventListener("click", () => {
page++;
content.textContent = `Page ${page}`;
history.pushState({ page }, "", `?page=${page}`);
});
// 戻る/進むで状態を復元
window.addEventListener("popstate", (e) => {
if (e.state?.page) {
page = e.state.page;
content.textContent = `Page ${page}`;
} else {
content.textContent = "初期ページ";
page = 1;
}
});
</script>
HTML- ポイント:
pushStateで履歴を積むと、戻る/進むでpopstateが発火。event.stateに保存したオブジェクトが入っている。
よく使うテンプレート集
タブ切り替えを履歴に反映
function showTab(tab) {
document.querySelectorAll(".tab").forEach(el => el.classList.add("hidden"));
document.getElementById(tab).classList.remove("hidden");
history.pushState({ tab }, "", `?tab=${tab}`);
}
window.addEventListener("popstate", (e) => {
const tab = e.state?.tab || "home";
showTab(tab);
});
JavaScript- ラベル: 戻る/進むでタブ状態を復元できる。
検索条件を履歴に保持
function applySearch(q) {
document.getElementById("result").textContent = `検索結果: ${q}`;
history.replaceState({ q }, "", `?q=${encodeURIComponent(q)}`);
}
window.addEventListener("popstate", (e) => {
const q = e.state?.q || "";
document.getElementById("result").textContent = `検索結果: ${q}`;
});
JavaScript- ラベル: 検索条件をURLに反映し、戻る/進むで復元。
実務でのコツ
- push vs replace:
pushState→ 履歴を積む(戻る/進むで辿れる)。replaceState→ 履歴を置き換える(戻る/進むでは辿れない)。
- popstateは「戻る/進む」で発火:
pushState直後には発火しない。ユーザー操作やhistory.back()で発火。 - stateオブジェクトを活用: 必要な画面状態(ページ番号、タブ名など)を保存しておくと復元が簡単。
- URLと状態を同期: SPAでは「URL=状態」として扱うと、ブックマークや共有も自然に動く。
ありがちなハマりポイントと対策
- pushState直後にpopstateが来ない:
- 対策: 直後は自分で画面更新を行う。戻る/進む時だけ popstate が発火。
- stateを保存し忘れて復元できない:
- 対策: 必要な情報は必ず第1引数に入れる。
- 外部URLを指定してエラー:
- 対策: 同一オリジン内のパスだけ変更可能。
練習問題(ページ番号付きリスト)
<ul id="list"></ul>
<button id="next">次へ</button>
<script>
const list = document.getElementById("list");
let page = 1;
function render() {
list.innerHTML = "";
for (let i = 1; i <= 5; i++) {
const li = document.createElement("li");
li.textContent = `Page ${page} - Item ${i}`;
list.appendChild(li);
}
}
document.getElementById("next").addEventListener("click", () => {
page++;
render();
history.pushState({ page }, "", `?page=${page}`);
});
window.addEventListener("popstate", (e) => {
page = e.state?.page || 1;
render();
});
render();
</script>
HTML- 効果: 「次へ」で履歴が積まれ、戻る/進むでページ番号が復元されます。
直感的な指針
- 「戻る/進むで状態復元」= popstate。
- pushStateで履歴を積み、stateに必要情報を保存。
- popstateで event.state を読んで画面を再構築。
- SPAや検索条件保持に必須の仕組み。
