DEV Community

terrierscript
terrierscript

Posted on

6 2

TIL - Vue.js Event Bus more clearly

Vue.js event bus technique is sometime useful.

// ModalEvent.js
import Vue from "vue"

export const ModalEvent = new Vue()
<script>
import Vue from "vue"
import VModal from "vue-js-modal"
import { ModalEvent } from "./ModalEvent"

Vue.use(VModal)

export default {
  created(){
    ModalEvent.$on("openModal", () => {
      this.$modal.show("hello-modal")
    })
  }
}
</script>
<!-- event trigger component -->
<script>
import { ModalEvent } from "./ModalEvent"

export default {
  methods:{
    onClick(){
      ModalEvent.$emit("openModal")
    }
  }
}
</script>

But it have tiny problem that Event.$on and Event.$emit 's event signature is string, and it's can easily mistake.

Solution

I found it's can solve with use 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)
    }
  }
})
<script>
import Vue from "vue"
import VModal from "vue-js-modal"
import { ModalEvent } from "./ModalEvent"

Vue.use(VModal)

export default {
  created(){
    ModalEvent.onOpenModal( () => {
      this.$modal.show("hello-modal")
    })
  }
}
</script>
<script>
import { ModalEvent } from "./ModalEvent"

export default {
  methods:{
    onClick(){
      ModalEvent.emitOpenModal()
    }
  }
}
</script>

SurveyJS custom survey software

Build Your Own Forms without Manual Coding

SurveyJS UI libraries let you build a JSON-based form management system that integrates with any backend, giving you full control over your data with no user limits. Includes support for custom question types, skip logic, an integrated CSS editor, PDF export, real-time analytics, and more.

Learn more

Top comments (4)

Collapse
 
rizkmeriouli profile image
Rizk MERIOULI

Hello, Terrierscript.
could you please guide me to test this modal vuejs component with JEST ?

import Vue from 'vue'
import { TeamMember } from '@/components/TeamMember.vue'
import { mount } from "@vue/test-utils"

describe('TeamMember.vue', ()=>{
it('renders a link', () => {
const wrapper = mount(TeamMember)
expect(wrapper.text(true)).toEqual(true)
})
})

Collapse
 
terrierscript profile image
terrierscript

Sorry for late ( I missed this comment.)

Hmm, this solution is un-test friendly ( I noticed this now )

If I need test this, I mocked ModalEvent.
use with jestjs.io/docs/en/manual-mocks#moc... or sinonjs.org/

Collapse
 
moe64 profile image
Moe

cool! I find Redux/Vuex really confusing, but this EventBus method looks like a simpler solution.

Collapse
 
dayvidwhy profile image
David Young

You can even use this technique while still making use of Vuex.

I like it the most when I want to avoid storing extra stuff in state, like having some vue instance commit a flag, that another vue instance is watching. That would be like a vue1 -> state -> vue2 pathway.

I can instead just use the EventBus as like a side passage, just emit from 1 vue component and listen to it in the other one so I'm instead going vue1 -> EventBus -> vue2.

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more