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