はじめに
前回からファイル投稿フォーム的なものを作っています。ページを移動する前に入力内容が消えても構わないか、一旦確認する、よくある確認ダイアログを出したいです。これまたNuxt2での例はそれなりにあったものの、Nuxt3でやってみた例が見当たらなかったのでやってみました。composableっていう機能がなんかすごく便利だなって個人的に思ってるのでcomposableでやります。
開発環境
- Nuxt 3.0.0-rc.1
- Vuetify 3.0.0-beta.1
ほしいイメージ
ページ移動時にこれが出てほしい
ページリロード時にこれが出てほしい
結果
過程をいっぱい書いても 興味ない方も居ると思うので出来上がったものをまず置いときます
import {
onBeforeRouteLeave, onBeforeRouteUpdate, NavigationGuardNext
} from 'vue-router'
const confirmText = "入力内容は破棄されます、本当に移動してもよろしいですか?"
const confirmVueRouter = (next: NavigationGuardNext) => {
const answer = window.confirm(confirmText)
if (answer) {
// ページを移動したら、確認ダイアログを表示しないよう戻す
window.removeEventListener("beforeunload", confirmBrowserRouter)
next()
}
}
const confirmBrowserRouter = (e: BeforeUnloadEvent) => {
e.preventDefault()
e.returnValue = confirmText
}
export default function () {
// Vue-routerでのページ移動時の確認ダイアログ発火
onBeforeRouteLeave((_to, _from, next) => {
confirmVueRouter(next)
})
onBeforeRouteUpdate((_to, _from, next) => {
confirmVueRouter(next)
})
// ページリロード時の確認ダイアログ発火
if (process.client) {
window.addEventListener("beforeunload", confirmBrowserRouter)
}
}
<script setup lang="ts">
// ページ移動前に確認をしたいページでこの関数を呼ぶだけ
useConfirmUnload()
</script>
過程
1: Vueの普通のやり方を調べる
window.addEventListener("beforeunload", 関数)
で ブラウザのページ遷移前に割り込みができ
onBeforeRouteLeave
で vue-routerのページ遷移前に割り込みができるらしい
2: Nuxt2でのやり方を調べる
既存のやり方を参考にさせて頂きました
3: next() 関数の型を調べる
2回書きたくなかったので 関数を引数として渡す関数を作りたく、
関数を引数に取るときの型定義ってどうするのか見てみた
ただ、VSCodeからnextの型定義まで移動したら 型がちゃんとexportされていたので
import { NavigationGuardNext } from 'vue-router'
で 型をそのまま使えた。
4: Routerをcomposable上で触る例を調べる
まだいまいちcomposableの書き方がわからないので
NuxtのDiscussionから既存の例を参考にさせていただいた
5: 完成
以上でいい感じに動くのができました。
ただ、beforeUnloadで出すダイアログのメッセージは いつの間にか変更できない仕様になってたようで
自環境では e.returnValueに何かが入っていれば規定の確認ダイアログが出るという振る舞いをしました。
まぁメッセージ変えられなくとも特に問題はないのでこれで完成とします。
読んでいただきありがとうございます。