Vue3.x系がリリースされてから1年が立ちました。nuxt.jsもVue3.x系が取り込まれた際の移行を意識して、Nuxt Composition APIを使った開発を行っています。Composition API以外にevent bus実装も違いがありましたので、紹介します。
目次
event busとは
コンポーネント間のイベント通知を支える機構で、イベントの監視、イベントの発行ができる機能をもった通信バスのことです。イベント駆動のパラダイム実装を行う上では、欠かせない機構です。
Node.jsのEventEmitterとは
近年のJavascriptフレームは、node.jsからフィードバックを受けていることも大きいので、Node.jsのイベント通知などの機構がどのように実現されているかみてみましょう。
Node.js のコアライブラリで、イベント駆動のパラダイムでのプログラミングをサポートするためにEventEmitterという仕組みが提供されています。このEventEmitter自体は、
- EventEmitter#on ・・・eventにlistenerを登録する
- EventEmitter#emit ・・・eventを発火させる
を提供しています。下記はemitterを利用したイベント発火、イベントの購読の例です。
const EventEmitter = require("events");
const emitter = new EventEmitter();
// ユーザ追加イベントの購読を開始する
emitter.on("addUser", (name) => {
console.log(name + 'さんが追加されました。')
})
・・・
// ユーザ追加イベントを発火させる
emitter.emit("addUser", username)
onメソッドは、イベント名、イベント発生時に処理するコールバックを受け取り、emitメソッドは、イベント名、コールバックに渡す引数を受け取ります。
2.x Syntaxのevent bus実現方法
グローバルなVueインスタンスを通して、イベントの購読、イベントの出版を行うことで実現していました。下記は、例です。
const eventBus = new Vue()
// ユーザ追加イベントの購読を開始する
eventBus.$on("addUser", (name) => {
console.log(name + 'さんが追加されました。')
})
・・・
// ユーザ追加イベントを発火させる
eventBus.$emit("addUser", username)
Vue2.x系では、$on、$offおよび$onceインスタンスメソッド削除されます。アプリケーションインスタンスは、イベントエミッタインターフェイスを実装しなくなりました。
3.xアップデートに伴う変更
Vue.jsのEvent APIドキュメントには、次のような記述があります。
We removed
$on,$offand$oncemethods from the instance completely.$emitis still a part of the existing API as it’s used to trigger event handlers declaratively attached by a parent component
$on, $off, $once自体が削除されます。そのため、別の方法に置き換える必要があります。
こちらでは、2つのライブラリmitt, tiny-emitterが紹介されています。vue2.x系では、下記のように、emitter()をインジェクションしていたようです。
import emitter from 'tiny-emitter/instance'
export default {
$on: (...args) => emitter.on(...args),
$once: (...args) => emitter.once(...args),
$off: (...args) => emitter.off(...args),
$emit: (...args) => emitter.emit(...args),
}
Vue3.x系では、Vue2.x系のemitを使いたい場合は、onGlobalSetup()を利用して、emitterを登録して、必要な部分でinject()を通してインスタンスを取得して、利用する感じで実装しておくと良いかもしれません。
今回は、NuxtにVue3.x系で取り込まれた際のeventBus機構について、Vue3.x系を取り込んでおいても大きなインパクトを受けないように対応する方法について紹介しました。お疲れ様でした。

