Vue + Mittでグローバルでイベントを取得できるようにする

Vue.jsで直接の親子関係がないコンポーネント間でデータのやりとりをしたい時がありました。
Vuexでやれよと言われたらそれまでですが、Vuexに頼りたくなかったこともあり、今回Mittというライブラリを使用してグローバルでイベントを取得できるようにしました。

Vue.js2系まではEventBusの$onと$off等を使えばグローバルでイベントを取得することができましたがVue.js3系ではこれが廃止されています。
公式ドキュメントでも代替案としてVue.js3系ではEvent Emitter (イベントエミッタ) インタフェースを実装したMitttiny-emitterのような外部ライブラリの使用を推奨しているようです。

公式ドキュメント

Mittをインストールする

npm install --save mitt

Mittの使い方

基本的に公式ドキュメントに記載されている通りで問題ないです。
emitter.emitでイベントを待機させておきemitter.onでイベントを読みにいきます。
Vue.jsのemitを使っていればあまり違和感なく使えるかと思います。

まずはemitter.js等の命名でmittのインスタンスを作るファイルを用意しておくとどこでも呼び出せるので便利です。
今回はある親子関係にないコンポーネント間でクリックが押された時のイベントを取得したかったのでemitter.emitでイベントを発行しておきます。

import mitt from 'mitt'
export const emitter = mitt()

/**
 * グローバルでクリックイベントを取得する
 * @param {object} e
 *
 * @return {object}
 */
export const handleClick = (e) => {
  emitter.emit('handleClick', e)
}

ボタンを押されたときにイベントが発行されるようにクリックメソッドを登録しておきます。
compositionAPIでも同じ要領で問題ないです。

<template>
  <div>
   <button @click="click($event)">ボタン<button/>
  </div>
</template>

<script>
import { handleClick } from 'emitter.js'

export default {
  methods: {
    click (e) {
      handleClick(e)
    }
  }
}
</script>

クリックイベントを見たいコンポーネントではmountedのタイミングでemitter.onを使用してイベントを取得できるように購読しておきます。

import { emitter } from 'emitter.js'

export default {
  mounted () {
    emitter.on('handleClick', e => {
      if (!Object.keys(e).length) {
        return false
      }
      console.log(e)
    })
  },
}

これによってComponentA.vueで発行されたイベントがComponentB.vueのコンポーネントで読みに行くことができるようになったかと思います。

Vuexのstoreを利用するにはちょっと歯がゆい場面などで中々重宝しましたので是非使ってみてください。

コメントを残す

入力エリアすべてが必須項目です。メールアドレスが公開されることはありません。

内容をご確認の上、送信してください。