On my previous article , I write how I implement a messaging system on microservices architecture and I used RabbitMQ as the message broker. The main concept of a messaging system is publish — subscribe pattern. On the simple word, in publish-subscribe pattern, there are services that publish message and there are others services subscribe to the message. The message can be an event, an object, or others type.
However, the publish-subscriber pattern not only implements on backend. In frontend, like web application and mobile application, we also can implement publish — subscribe pattern. If in backend world the message sends through service to service, meanwhile in frontend world the message send through component to component.
In backend world, we can use RabbitMQ, Apache Kafka, and Google PubSub as the message broker, but what we can use as the message broker for frontend world? There is a lot of libraries that we can use. If we want to implement publish — subscribe for an Android application we can use EventBus and for an iOS application we can user SwiftEventBus . So what can we use for Vue JS app?
Vue JS Is Enough — Let me show you
Before we jump to the code, it is better if we know the problem statement. Here is the problem statement.
I have two components. I will pass data from one component to another component. The receiver should show the received data.
I think the problem statement is clear enough. So let’s write the code and see how Vue as a message broker.
Create new Vue App
To create new Vue CLI application, run the command below. Make sure you had installed Vue CLI.
Install Vue CLI, if you not installed it yet
npm install -g @vue/cli
Create vue app
vue init webpack <project-name>
Start the project
npm run dev
Create Components
Now I will create two components. One of them will be the publisher and another one will be the subscriber. The component for the publisher named as Leftside.vue and the subscriber is Rightside.vue.
Here the code for Leftside.vue.
<template>
<div class="left-side">
<div class="content">
<div>
<label for="location"> Location </label>
<input type="text" name="location" v-model="location" />
</div>
<div>
<label for="caption"> Caption </label>
<input type="text" name="caption" v-model="caption" />
</div>
<input type="submit" v-on:click="sendData" value="Send">
</div>
</div>
</template>
<script>
export default {
data () {
return {
location: '',
caption: ''
}
},
methods: {
sendData () {
return ''
}
}
}
</script>
<style scoped>
.left-side {
width: 50%;
height: 500px;
float: left;
background-color: #35495e;
}
input[type=submit] {
width: 100%;
background-color: #42b883;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
border-radius: 4px;
cursor: pointer;
}
input[type=text], select {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
</style>
Here is the code for Rightside.vue.
<template>
<div class="right-side">
<div class="content">
<p> {{ data.location }} </p>
<p> {{ data.caption }} </p>
</div>
</div>
</template>
<script>
export default {
data () {
return {
data: {
location: 'Location placeholder',
caption: 'Payload placeholder'
}
}
},
methods: {
}
}
</script>
<style scoped>
.right-side {
width: 50%;
height: 500px;
float: right;
background-color: #42b883;
border: 1px;
border-color: black;
}
</style>
And then I need to use these components on my Helloword.vue, the generated file.
The next step is creating the Vue instance as the event bus. Now, create a new file on your /src directory, name it eventBus.js . The eventBus.js is very simple, we only need two lines of code for it 😃
The next is we will use this eventBus.js in our components. Look at the updated code below.
import Vue from 'vue'
export default new Vue()
Here is the updated Leftside.vue.
<template>
....
</template>
<script>
import EventBus from '../eventBus'
export default {
data () {
return {
location: '',
caption: ''
}
},
methods: {
sendData () {
const payload = {
location: this.location,
caption: this.caption
}
EventBus.$emit('DATA_PUBLISHED', payload)
}
}
}
</script>
<style scoped>
....
</style>
Here is the updated Rightside.vue.
<template>
....
</template>
<script>
import EventBus from '../eventBus'
export default {
data () {
return {
data: {
location: 'Location placeholder',
caption: 'Payload placeholder'
}
}
},
methods: {
updateData (payload) {
this.data = payload
}
},
mounted () {
EventBus.$on('DATA_PUBLISHED', (payload) => {
this.updateData(payload)
})
}
}
</script>
<style scoped>
....
</style>
You can see at the code, in each component I imported the eventBus.js. The EventBus object used as the message broker.
Publish
In the Leftside.vue, you will see
EventBus.$emit('DATA_PUBLISHED', payload)
The emit() method is used to publish the message. It receives two parameters. The first is the event name and the second is the data to be passed.
Subscribe
In the Rightside.vue, you can look at
EventBus.$on('DATA_PUBLISHED', (payload) => {
this.updateData(payload)
})
The on() method is used to listen to the event that on the EventBus. It receives two parameters. The first is the event name and the second is the callback method.
The DATA_PUBLISHED is the event name that used to identify which event the publisher publishes and subscriber subscribes. It is the same as the topic name when we use RabbitMQ. As simple as that 😄
Actually, there are two other methods that we can use, those are off() and once(). The off() is used to remove the subscribed event and once() is used to subscribe to an event but only triggered once. After the subscriber triggered, the subscription will be removed. For more detail, you can check the official documentation
here
.
Another cool stuff that I had done with Vue as event bus is triggering another component to reload its data by fetching from services. I don’t need to reload all page to update the data, it will be done by the component itself.
Actually, there are others communication pattern that we can use in our daily project. I’m myself also still learning others patterns and looking where I can implement the publish — subscribe pattern. If you have any idea where I can implement it, feel free to reach me at ecojuntak@gmail.com. Oh ya, you can find the full code on my repository.
ecojuntak/vue-event-bus
Vue event bus demo
See you on my next post and I hope you love it.
Cappy Hoding! 🖖🏾