ブラウザの更新ボタンがクリックされた時には、通常はページのリロードが行われますが、その際に特定の処理を行いたい場合があります。例えば、変更が保存されていない場合に確認メッセージを表示したり、特定のデータをサーバーに送信したり等々。
更新ボタンが押されたタイミングで、JavaScriptを実行する方法を見ていきましょう。ただし、ユーザーにとってうざったい挙動になりがちなので、その点は注意してください。何かしらの管理画面で使う等の利用に留めるべきです。僕の仕事ではCMSの管理画面のリニューアルで使用しました。ユーザビリティの観点から一般のウェブページでは利用しない方が良いと思います。
また、Wordpressのプラグインなどでキャッシュを有効にすると以下の内容は発火しないようなので気を付けましょう……(実験済み)iOSのSafariでは処理に限界があるようです……
beforeunloadを使って解決
beforeunload
イベントは、ページがアンロード(unload)される直前に発生し、ページの更新時にも発火します。次のようにJavaScriptを記述することができます。
window.addEventListener('beforeunload', function (event) {
});
jQueryを利用する場合は以下のようになりますね。
$(window).on('beforeunload', function (event) {
});
アンロードというのは「ブラウザが現在のページを離れる」という意味で使われるので、必ずしも更新ボタンが押されたタイミングを検知するわけではないことに注意です。具体的なシーンとしては「ページの更新」「新しいページへの移動」「ブラウザのタブを閉じる」のパターンが挙げられます。
beforeunload
イベントは、ページが上記のタイミングでアンロードされる直前に実行したい処理を記述するために利用しますので留意しておきましょう。
話をもどして、上記のサンプルで何らかの処理を追加したい場合はpreventDefault()
で一旦アンロードを止める必要があります。preventDefault()
を入れないとそのままアンロードが進行して思うような挙動にならないので要チェックです。
window.addEventListener('beforeunload', function (event) {
event.preventDefault(); // デフォルトの動作(アンロード)の進行を止める
// 以降、実行したい処理
});
event.returnValueは非推奨
古いウェブページによっては(比較的新しい記事でも……)event.returnValue = '表示させたい文字'
を実装例で挙げている場合がありますが、こちらは非推奨でWeb標準ではなくなっています(mdn web_docs)。実際に2024年7月現在、Google Chrome(ver.126.0.6478.127)では動作せず、ブラウザ標準の文字列しか表示されません。
return false;では画面遷移を防げない
beforeunload
イベントの最後にreturn false;
を追加すると画面遷移や更新を防ぐことが出来そうですが、ブラウザの仕様によりこの挙動は不可です。現状のブラウザではconfirm
も動作しません。なので遷移するかどうかを尋ねるダイアログはブラウザ標準のみの利用になると考えた方が良いです。
更新ボタンのみで動作させたい場合
beforeunload
イベントは、更新、画面遷移、タブの終了などアンロード(unload)される直前すべてに適用されてしまいます。
もしどうしても厳密に更新ボタンのみを検知したい場合は以下の様にブラウザのナビゲーション情報を取得して分岐させる必要があります。
window.addEventListener('beforeunload', function (event) {
event.preventDefault();
let navType = window?.performance?.getEntriesByType("navigation")[0]?.type;
if (navType === 'reload') { // もちろんswitch文でも可です
console.log('更新されますよ');
}
});
window?
やperformance?
が微妙に分からない方もいるかと思いますので簡単に説明します。プロパティの直後の「?」はオプショナルチェイニング演算子と言って、オブジェクトのプロパティやメソッドに安全にアクセスするための演算子です。もし左側のオブジェクトが null
または undefined
の場合、右側のプロパティアクセスやメソッド呼び出しを試みずに undefined
を返します。JavaScriptの構文エラーを防ぐことが出来ますね。
一応ナビゲーションタイプの対応表を掲載しておきます。
navigate | ページが通常のナビゲーション(リンククリックなど)によって読み込まれた場合 |
reload | ページがブラウザの更新ボタンや location.reload() メソッドによって再読み込みされた場合 |
back_forward | ブラウザの戻るや進むボタンによって移動した場合 |
prerender | ページがプリレンダリングされた後、実際にユーザーに表示された場合 |
よっぽどの事情がない限りbeforeunload
は利用しないとは思いますが、もしページの離脱や設定の保存状態を確認したい場合などに使えるので是非記憶にとどめておくことをお勧めします。