With Vue 3, I've the following component structure:

As you can see, ChildA is able to communicate with ChildB and ChildB must be able to change its state accordingly.
With Vue 2, I was able to send an event in ChildA:
this.$root.$emit('new-message', data)
And then handle it in ChildB:
this.$root.$on('new-message', (data) => {
this.state = data
})
But since Vue 3, $on, $once and $off have been removed. How can I achieve this communication in Vue 3 ?
If you have a data attribute, in this example just called data, then you can use reactive to create a simple store, which can then be imported by both sibling components (in this example Component A and B)
// store.js
import { reactive } from 'vue'
export const store = reactive({
data: 'New Message',
setData(something) {
this.data = something;
},
})
<!-- ComponentA.vue -->
<script>
import { store } from './store.js'
export default {
data() {
return {
store
}
}
}
</script>
<template>From A: {{ store.data }}</template>
And
<!-- ComponentB.vue -->
<script>
import { store } from './store.js'
export default {
data() {
return {
store
}
},
watch: {
// If you need to trigger an event on change, then:
'store.data'(newData, oldData) {
console.log('Data Changed', { newData, oldData });
}
},
}
</script>
<template>From B: {{ store.data }}</template>
When the state in the store updates, the changes will be reflected in all child components that use it. This should be simpler than the Vue 2 $emit pattern, as you don't need to manage tracing events through the component tree.