skysan's programming notebook

コーディングして思ったことなどを気ままに

続・モーダルなコンポーネントのフォーカス管理(Nuxt.js版)

やりたいこと

Nuxt.jsでもVue.js同じようなフォーカス管理をしたい。

skysan87.hatenablog.com

背景

Vue.jsで作ったものを利用しようとすると以下のエラーが出てしまい、うまくいかない。

document undefined

公式の回避方法もうまくいかない。

解決策

カスタムディレクティブを使用する。

1. カスタムディレクティブの作成

  • plugins/focusin.js
import Vue from 'vue'

Vue.directive('focusin', {
  inserted (el, binding) {
    const f = (evt) => {
      if (binding.value(evt, el)) {
        window.removeEventListener('focusin', f, false)
      }
    }
    window.addEventListener('focusin', f, false)
  }
})

2. Configに設定

  • nuxt.config.js
  plugins: [
    { src: '@/plugins/focusin', ssr: false }
  ],

3. コンポーネントに実装

v-focusinという名称でディレクティブが利用できるようになる。

<template>
<div>
  <div tabindex="0" class="dummy" v-focusin="checkFocus"></div>

  <!-- モーダルダイアログの要素 -->
  <div class="modal-body">
    <input class="input-text" type="text" v-model="comment" ref="modalComment" />
  </div>

  <div tabindex="0" class="dummy" v-focusin="checkFocus"></div>
</div>
</template>

<script>
export default {
...省略
  methods: {
    checkFocus (ev) {
      if (ev.target !== null && ev.target.className === 'dummy') {
        this.$refs.modalComment.focus()
      }
    }
  }
}
</script>

参考記事

Nuxt.js でスクロールでふわっと要素が出現するやつを「カスタムディレクティブ」で実装する