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>
Top comments (4)
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)
})
})
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/
cool! I find Redux/Vuex really confusing, but this EventBus method looks like a simpler solution.
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.