
JavaScriptで離脱防止アラートを表示する(ブラウザバック・リロード・タブ閉じ)
2022.03.31
リロード・タブが閉じられる時の対応
保存されていないデータがあるときに、誤ってページを閉じてしまわないようにアラートを出すやり方を紹介します。ブラウザで戻るボタンやリロードボタンが押された時、タブを閉じようとしたときに動きます。
beforeunloadを使います。ウィンドウや文書がアンロード(リロードやタブを閉じる)時のイベントです。同様に onbeforeunload でも設定できますが、addEventListener の方が推奨されています。
1 2 3 4 5 6 7 8 9 10 | window.addEventListener('beforeunload', (e: BeforeUnloadEvent) => { const message = '入力内容が保存されない可能性があります。ページを離れますか?' e.preventDefault() e.returnValue = message return message }) window.onbeforeunload = (e: BeforeUnloadEvent) => { // ... }) |
returnValueなどを設定してはいますが、表示させる文章を操作することはできません。
以前は指定可能だったようですが、よろしくないメッセージ(「ページを離れるとウイルスにかかるぞー!」みたいな)が設定されることもあったため、現在はブラウザごとに規定の文章になっているようです。
ブラウザバック時の対応
基本的には popstate イベント を利用します。
履歴がスタック状にブラウザに記録されている中で、その記録を取り出すときのイベントです。ブラウザバック時、このイベントが実行されています。
1 2 3 4 5 | window.history.pushState(null, document.title); // 必要であれば、セッション履歴スタックに状態を追加 window.addEventListener('popstate', () => { // 任意の処理 // history.back()やhisotry.go()などを用いて任意のページに移動するようにします }); |
注意点:MDNにも書いてあるように、実行されるとキャンセルできません。それを踏まえた上での実装を!
調べていると、popstateを使用せず、onhashchangeなどハッシュの変更を検知することで、ブラウザバックの対応をすることもあるそうです。状況に合わせて使いたいですね。
各フレームワーク・ライブラリの使えそうなメソッド
ブラウザバック時などに使えそうな各ライブラリ・フレームワークのメソッドをいくつか見つけたので、軽くご紹介します。
Vue
Vue Router - beforeRouteLeave
編集中に誤って経路を離れるのを防ぐ時を想定して作られてます。
詳細:ナビゲーションガード | Vue Router
1 2 3 4 5 6 7 | beforeRouteLeave (to, from, next) { if (window.confirm('入力内容が保存されない可能性があります。ページを離れますか?')) { next() } else { next(false) } } |
React
先に React での注意点です。アンマウント時にイベントを解除しておかないと、該当箇所以外でもイベントが実行されます!
1 2 3 4 5 6 | useEffect(() => { // addEventListenerなどでイベント登録 return () => { // removeEventListenerなどでイベント解除 } }, []) |
react-router-dom - history.block
react-routerの中に入っているweb用のルーターライブラリ。
そのhistory.blockも編集中に誤ってページを離れるのを防ぐのに適してます。
詳細:Blocking Transitions
1 2 3 4 5 6 7 8 9 10 11 12 | // 表示するメッセージを指定 history.block('入力内容が保存されない可能性があります。ページを離れますか?') // ブロック解除 history.block(true) // 任意の処理もできる history.block(() => { if (window.confirm('入力内容が保存されない可能性があります。ページを離れますか?')) { // ... } }) |
Next.js - router.beforePopstate
popstate が起きる前に処理を追加できます。
詳細:next/router router.beforePopState|Next.js
1 2 3 4 5 6 7 8 | useEffect(() => { router.beforePopState(({ url, as, options }) => { if (as === '/about') { return false // falseを返すとNext.jsはpopstateを処理しない } return true }) }, []) |
さいごに
デフォルトのJavaScriptだけでなく、ライブラリのメソッドもご紹介しましたが、状況に適したやり方を使っていけたらいいですね!
書いた人はこんな人

- Webエンジニア。
好きなものはフルーツタルト。
IT技術10月 25, 2023Renovateのおすすめ設定
IT技術4月 10, 2023tRPCを触ってみる
IT技術1月 10, 2023Webアクセシビリティとエンジニア
IT技術10月 14, 2022知ってると便利なCSS 8選!