このダイアログの表示機能をVueのmixinsとして実装していきます。
まず、あのアラート表示の実態はwindowオブジェクトのbeforeunload
イベントです。
それをEventListenerに登録/解除する処理をVue.jsのmixinsに切り出します。
ポイントを順番に解説していきます。
まず、ページ離脱時に出したい場合、Componentのライフサイクルフックではリロードなどに対応できないため、Vueのナビゲーションガードを用います。該当するのはbeforeRouteLeave
です。
beforeRouteLeave
はvue-class-componentを用いてComponentに登録することで使用することができます。
そのためmixins的な機能ですが、今回はvue-mixin-decoratorを使わず実装しました
Component.registerHooks(['beforeRouteLeave']);
beforeRouteLeaveでルーティングをブロックできるようにフラグを用意しておきます
enabledWhenUnloadConfirm: boolean = false;
beforeRouteLeave({ next }): void {
if (this.enabledWhenUnloadConfirm) {
next(false);
return;
}
next();
}
ダイアログの出現条件はそれぞれenableConfirm
, disableConfirm
を実行することで制御できるようにします。
enableConfirm(): void {
this.enabledWhenUnloadConfirm = true;
window.addEventListener('beforeunload', this.onBeforeunloadHandler, false);
}
disableConfirm(): void {
this.enabledWhenUnloadConfirm = false;
window.removeEventListener(
'beforeunload',
this.onBeforeunloadHandler,
false
);
}
Componentのライフサイクルフックに合わせてbeforeunloadイベントの登録と解除を自動的に行うようにしておきます
created() {
window.addEventListener('beforeunload', this.onBeforeunloadHandler, false);
}
beforeDestroy() {
window.removeEventListener(
'beforeunload',
this.onBeforeunloadHandler,
false
);
}
また、度々出現しているonBeforeunloadHandler
は自前の関数で、__現在IEとEdgeのみ__ですがダイアログのメッセージをカスタムできるのでしています。他ブラウザはセキュリティの観点でメッセージが固定されています。
onBeforeunloadHandler(evt: BeforeUnloadEvent): void {
evt.returnValue = '編集中の内容は失われます。よろしいですか?';
}
これらをまとめた最終的なファイルは以下のようになります。
import Vue from 'vue';
import Component from 'vue-class-component';
Component.registerHooks(['beforeRouteLeave']);
@Component
export default class ConfirmWhenUnload extends Vue {
enabledWhenUnloadConfirm: boolean = false;
created() {
window.addEventListener('beforeunload', this.onBeforeunloadHandler, false);
}
beforeDestroy() {
window.removeEventListener(
'beforeunload',
this.onBeforeunloadHandler,
false
);
}
beforeRouteLeave({ next }): void {
if (this.enabledWhenUnloadConfirm) {
next(false);
return;
}
next();
}
onBeforeunloadHandler(evt: BeforeUnloadEvent): void {
evt.returnValue = '編集中の内容は失われます。よろしいですか?';
}
enableConfirm(): void {
this.enabledWhenUnloadConfirm = true;
window.addEventListener('beforeunload', this.onBeforeunloadHandler, false);
}
disableConfirm(): void {
this.enabledWhenUnloadConfirm = false;
window.removeEventListener(
'beforeunload',
this.onBeforeunloadHandler,
false
);
}
}
これを、ダイアログを表示したいページで呼んで適宜
this.enableConfirm();
this.disableConfirm();
を実行することでダイアログの出現を制御できるようになります