前回の反省
カスタムディレクティブで作ってみたが、ダイアログが埋め込んであるページに遷移する度にfocusin
イベント登録が発生してしまう。
今回やりたいこと
- カスタムディレクティブをやめる。
- 以下のサイトを参考にダイアログを動的に生成し、表示中のみ
focusin
イベントが動くようにする。
結果
- SPAモードでのみ動作確認
ダイアログコンポーネントの実装
- Dialog.vue
<template> <div> <div tabindex="0" class="dummy"></div> <!-- モーダルダイアログの要素 --> <div> <input type="text" ref="modalComment" /> </div> <div> <button @click="close">OK</button> </div> <div tabindex="0" class="dummy"></div> </div> </template> <script> export default { props: { parent: { type: Element, require: true } }, mounted () { this.parent.appendChild(this.$el) this.$nextTick(() => { this.$el.focus() this.$refs.modalComment.focus() // ダイアログ生成時にイベント登録 document.addEventListener('focusin', this.checkFocus, false) }) }, destroyed () { // ダイアログ破棄時にイベント解除 document.removeEventListener('focusin', this.checkFocus, false) this.$el.remove() }, methods: { close () { this.$emit('update', this.$refs.modalComment.value) this.$destroy() }, checkFocus (ev) { if (ev.target !== null && ev.target.className === 'dummy') { this.$refs.modalComment.focus() } } } } </script>
ダイアログを呼ぶ方
import Vue from 'vue' import dialog from '@/components/Dialog.vue' const DialogController = Vue.extend(dialog) export default { data () { return { dialog: null } }, methods: { openDialog () { this.dialog = new DialogController({ propsData: { parent: this.$root.$el //親要素は構成によって変わる } }) this.dialog.$on('update', (comment) => { console.log(comment); }) this.dialog.$mount() } }
所感
・モーダル管理が楽になった。