🌑

ページ離脱時にアラートを出したかった

に公開

概要

Nuxtで以下の方法でページ離脱をするときに window.confirm('hogehoge') してOKならそのまま遷移、キャンセルなら留まるみたいなことをしたかった

  • リロード(離脱というかコンポーネントのunmount)
  • 単純にどっか行く
  • ブラウザの「戻る」ボタン

😥できなかったこと1: beforeunloadイベントの追加

export default defineComponent({
  setup() {
    const handleBeforeUnload = () => {
      const isConfirm = window.confirm('hogehoge')
      if (!isConfirm) return false
    }

    onMounted(() => {
      window.addEventListener('beforeunload', handleBeforeUnload)
    })
    onBeforeUnmount(() => {
      window.addEventListener('beforeunload', handleBeforeUnload)
    })
  }
})

これをすると、コンソールに Blocked confirm('hogehoge') during beforunload が出る

😰できなかったこと2: onBeforeUnmount()の使用

export default defineComponent({
  setup() {
    onBeforeUnmount(() => {
      const isConfirm = window.confirm('hogehoge')
      if (!isConfirm) return false
    })
  }
})

onBeforeMount()の説明としてドキュメントには

コンポーネントインスタンスがアンマウントされる直前に呼び出されるフックを登録します。

と書いてあるため一見いけそう。
だが、厳密には アンマウントされることが決まっているコンポーネントに対してやり残したことはあるか?? なので、ここでisConfirmがfalseになろうとコンポーネントはアンマウントされる道を辿ってしまう。

😭できなかったこと3: beforeRouteLeaveの使用

どうやらVue Routerを入れているとbeforeRoutLeaveなるものを使用できるらしい

export default defineComponent({
  beforeRouteLeave (to, from, next) {
    const isConfirm = window.confirm('hogehoge')
    if (isConfirm) {
      next()
    } else {
      next(false)
    }
  },
  setup() {}
})

ただ、これだとリロードによるアラート表示はできず、単純にどっか行く方のアラート表示しかできない

暫定

できるところはbeforeRouteLeaveを使いつつ、リロードの対応は

export default defineComponent({
  setup() {
    const handleBeforeUnload = (e: Event) => {
      e.preventDefault()
      e.returnValue = true
    }

    onMounted(() => {
      window.addEventListener('beforeunload', handleBeforeUnload)
    })
    onBeforeUnmount(() => {
      window.addEventListener('beforeunload', handleBeforeUnload)
    })
  }
})

のようにするとブラウザが定めた文言のアラートが出るので、一旦それで我慢。
本当は1つの機能?なので1つの処理で対応したい気持ち。

ちなみに

e.preventDefault()
e.returnValue = true

の書き方をしているものがよく見受けられたが、returnValueは非推奨になっているっぽいので e.preventDefault() だけでいいかも

Discussion