• トップ
  • ブログ一覧
  • JavaScriptで離脱防止アラートを表示する(ブラウザバック・リロード・タブ閉じ)
  • JavaScriptで離脱防止アラートを表示する(ブラウザバック・リロード・タブ閉じ)

    岡坂(エンジニア)岡坂(エンジニア)
    2022.02.08

    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だけでなく、ライブラリのメソッドもご紹介しましたが、状況に適したやり方を使っていけたらいいですね!

    岡坂(エンジニア)

    岡坂(エンジニア)

    おすすめ記事