When you pass props from parent to children, you might need to update this data.
In vuejs you have two ways to handle this case, the most used is to emit
an event from the children to the parent. The other way is to use bus event
.
Emit event from children
In component paradigm, we have a component in the component in component ... From one parent you can pass multiple data in another child component, called props
.
In some cases, you will need to update these props from one of these ** child components**!
Should you update these props directly? NO!
If you try to make this on a props object, vue will trigger a warn
about this manipulation. You mustn't DO this!
⚠️ Mutating props like this is considered to be an anti-pattern!
Two rules:
Only the component can change its state
Only the parent of the component can change the props
So how can you update the props from children properly ?!
Use emit event
!
1) Emit an event from the child component with the new value to update the props in this event.
2) Handle this event in the parent and update the data!
A short example 👇
Context: We need to update props when clicking on
Child.vue
<template>
<div>
<!-- When we click on button, we want to update value -->
<button @click="updateCounter(counter + 1)">
</div>
</template>
<script>
import Vue from "vue"
export default Vue.extend({
props: {
counter: Number,
},
methods: {
updateCounter(newValue) {
// 1) Emit event from child with the new value
this.$emit('update-counter', newValue)
}
}
})
</script>
Parent.vue
<template>
<div>
<child
:counter="counter"
<!-- 2) We handle the update event and we update the current props value ! -->
@update-counter="counter = $event"
/>
</div>
</template>
<script>
import Vue from "vue"
// We omit Child component import
export default Vue.extend({
components: {
Child,
},
data() {
return {
counter: 0,
}
},
})
</script>
As you can see it can be easy to update props value from children! If you have more deep children like this 👇
Parent -> Child one -> Child Two
Child two has two parents, Parent and Child One.
If you need to update props from Child two, you can emit an event to Child One, and emit another event to Parent!
In general, this tip is efficient, but in some cases, you will need to communicate from one component to another component that is not linked by parent, for example, imagine that your Footer needs to communicate with your Header.
You cannot emit events between them!
How to handle this?
Bus Event
Vue allows us to use bus events!
It's a way to emit data between both components without using Parent !
First, we need to create our bus event!
import Vue from 'vue'
import App from './App.vue'
export const bus = new Vue()
new Vue({
render: h => h(App),
}).$mount('#app')
Footer.vue
<script>
import Vue from "vue"
// We omit template and bus import
export default Vue.extend({
methods {
emitValueWithBus(value) {
// Emit value thanks to the bus
bus.$emit('update-value', 'toto')
}
},
})
</script>
Header.vue
<script>
import Vue from "vue"
// We omit template and bus import
export default Vue.extend({
// Init the bus connection when created component
created () {
// Get value from event with the bus event
bus.$on('update-value', (data) => {
// data is equal to 'toto' !
})
},
destroyed() {
// When component is destroyed we should remove listener
bus.$off()
}
})
</script>
📝 Note: We remove listener manually, vue handle this case for bus event automatically
Conclusion
As we have seen before if you need to update props value you need to handle it in the parent component thanks to event
!
But in some cases we can't use these tips, so we need to use the event bus
!
I hope you like this reading!
🎁 You can get my new book Underrated skills in javascript, make the difference
for FREE if you follow me on Twitter and MP me 😁
Or get it HERE
☕️ You can SUPPORT MY WORKS 🙏
🏃♂️ You can follow me on 👇
🕊 Twitter : https://twitter.com/code__oz
👨💻 Github: https://github.com/Code-Oz
And you can mark 🔖 this article!
Top comments (2)
Great! Thank you for that, yesterday I started creating my todo app and was stuck exactly on emit, and couldn't find a way to make it work, but thanks to your tutorial it's working!
Wow very nice comment! I am so happy to see that it can help some people 👍😁