LoginSignup
50
43

More than 5 years have passed since last update.

Vue.jsでEventBusを利用して別にマウントしたコンポーネントやjQueryからイベントを受け取る

Posted at

例えばVue.jsでモーダルを実装し、それを開くフックは別なところに引っ掛けたい、みたいなパターンでどうするか?

EventBusを利用する

この解決として、EventBusというのが公式に提案されている

new Vue()でインスタンスを生成し、それを仲介してイベントを疎通しあう、という物になる。
windowグローバルにイベントを飛ばしたりするのと実質は変わらないが、ある程度キレイに実装出来そうだと感じる。

Modalでのサンプル

ベース

今回の基礎となるModalEventはこういう感じでシンプル。

ModalEvent.js
import Vue from "vue"

export const ModalEvent = new Vue()

今回はModalのvue-js-modalを利用する。

<!--HelloModal.vue -->
<template>
  <modal name="hello-modal">
    <div class="container">
      Hello!
    </div>
  </modal>
</template>

<script>
import Vue from "vue"
import VModal from "vue-js-modal"
// ModalEventをimportする
import { ModalEvent } from "./ModalEvent"

Vue.use(VModal)

export default {
  created(){
    // created / mountedでMountEventをlistenさせて、modalを開く
    ModalEvent.$on("openModal", () => {
      this.$modal.show("hello-modal")
    })
  }
}
</script>

別々にmountしたvueコンポーネント

index.html
   :
    <div id="app">
      <modal-open-button></modal-open-button>
      <hello-modal></hello-modal>
    </div>
   :

Modalを開く側のボタンはこんな具合になる

<!--ModalOpenButton.vue-->
<template>
  <div>
    <button @click="onClick">Open from Vue</button>
  </div>
</template>

<script>
import { ModalEvent } from "./ModalEvent"

export default {
  methods:{
    onClick(){
      // クリックしたらイベントを発火
      ModalEvent.$emit("openModal")
    }
  }
}
</script>

これでModalEventを介してイベントが疎通して開くようになる

jQueryの場合

あんまり用途は無い(ことが望ましい)が、jQueryから発火するのも出来るようになった。

index.html
    <div id="app">
      <div>
        <button id="jquery-external-button">Open from jQuery</button>
      </div>
      <hello-modal></hello-modal>
    </div>
import $ from "jquery"
import { ModalEvent } from "./ModalEvent"

$(function(){
  $("#jquery-external-button").click(function(){
    ModalEvent.$emit("openModal")
  })
})

vanillaなjsからの発火

jQueryとさして変わらないが、もう一歩踏み込んでjQueryも使わない場合。
あまりキレイではないが、windowにModalEventを渡して呼び出せる。

import Vue from "vue"
export const ModalEvent = new Vue()
window.ModalEvent = ModalEvent
index.html
    <div id="app">
      <div>
        <button id="vanilla-external-button">Open from Vanilla</button>
      </div>
      <hello-modal></hello-modal>
    </div>
    <!-- built files will be auto injected -->
    <script>
      document.onreadystatechange = function(){
        var elm = document.getElementById("vanilla-external-button");
        elm.onclick = function(){
          window.ModalEvent.$emit("openModal");
        }
      }
    </script>

おまけ:もうちょっとEventを整然とする

無造作にEventを飛ばすのを防ぐのに、methodsで限定しておくと少しは整然とするであろう。

ModalEvent.js
import Vue from "vue"

const OPEN_MODAL = "openModal"
export const ModalEvent = new Vue({
  methods: {
    emitOpenModal(event){
      this.$emit(OPEN_MODAL, event)
    },
    onOpenModal(cb){
      this.$on(OPEN_MODAL, cb)
    }
  }
})

参考資料

50
43
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
50
43