Works by

Ren's blog

@rennnosuke_rk 技術ブログです

【Vue.js】Event Busによる親コンポーネントから子コンポーネントへのイベント伝播

f:id:rennnosukesann:20181217223208p:plain:w300

一般に、Vueで親コンポーネントから子コンポーネントへのプロパティ操作を行う場合、親コンポーネントの値を子コンポーネントにバインドします。
では子コンポーネントのメソッド操作を行う場合はどうするかというと、直接的には $refs を通して子コンポーネントのメソッド呼び出しを行う方法があります。

// 子
const child = new Vue({
  methods: {
    hoge: function () {
      console.log('hoge...');
    }
  },
  template: '<template>child.</template>'
})

// 親
const parent = new Vue({
  components: {
    child
  },
  methods: {
    hoge: function () {
      this.$refs.child.hoge(); // 子コンポーネントメソッド呼び出し
    }
  },
  template: '<template><child ref="child"/></template>'
})

しかしながら、このような直接呼び出しは公式でも示されている通り非推奨です

代わりに、Event Busを用いた子コンポーネント処理呼び出しの方法があります。

// EventBus
const bus = new Vue();

// 子
const child = new Vue({
  created: function () {
    bus.$on('hoge', this.hoge); // hogeイベントハンドラ登録
  }
  methods: {
    hoge: function () {
      console.log('hoge...');
    }
  },
  template: '<template>child.</template>'
})

// 親
const parent = new Vue({
  components: {
    child
  },
  methods: {
    hoge: function () {
      bus.$emit('hoge'); // hogeイベント発火
    }
  },
  template: '<template><child ref="child"/></template>'
})

Event Bus自体は単純Vueコンポーネントオブジェクトです。
EventBusの $on メソッドでイベントハンドラの登録を行います。第2引数にはイベント発火時に呼び出される関数を登録します。
イベントの発火はEventBusの $emit を呼び出して行います。

コンポーネントで予めイベントハンドラとして呼び出される関数を登録しておき、
コンポーネントでは子コンポーネント関数を呼び出したいタイミングでイベントの発火を行います。

このようなイベント駆動によってメソッド呼び出しを行うことで、子コンポーネントの実装による親コンポーネントの実装の変更は発生しにくく、コンポーネント間の依存度を低く抑えることができます。 ただし、予め発生するイベントシグナルについては親子間で合意しておく必要があります。


小規模アプリのイベント伝播ではEventBusが役に立ちます。
ただし、中規模以上のアプリケーションを使用する場合はEventBusに登録するイベントが氾濫してしまうので、Vuex を使用した状態管理/イベント伝播を使用すると良いと思います。