$on
, $off
and $once
instance methods are removed. Component instances no longer implement the event emitter interface.
In 2.x, a Vue instance could be used to trigger handlers attached imperatively via the event emitter API ($on
, $off
and $once
). This could be used to create an event bus to create global event listeners used across the whole application:
// eventBus.js const eventBus = new Vue() export default eventBus
// ChildComponent.vue import eventBus from './eventBus' export default { mounted() { // adding eventBus listener eventBus.$on('custom-event', () => { console.log('Custom event triggered!') }) }, beforeDestroy() { // removing eventBus listener eventBus.$off('custom-event') } }
// ParentComponent.vue import eventBus from './eventBus' export default { methods: { callGlobalCustomEvent() { eventBus.$emit('custom-event') // if ChildComponent is mounted, we will have a message in the console } } }
We removed $on
, $off
and $once
methods from the instance completely. $emit
is still a part of the existing API as it's used to trigger event handlers declaratively attached by a parent component.
Migration build flag: INSTANCE_EVENT_EMITTER
In Vue 3, it is no longer possible to use these APIs to listen to a component's own emitted events from within a component. There is no migration path for that use case.
Static event listeners can be added to the root component by passing them as props to createApp
:
createApp(App, { // Listen for the 'expand' event onExpand() { console.log('expand') } })
The event bus pattern can be replaced by using an external library implementing the event emitter interface, for example mitt (opens new window) or tiny-emitter (opens new window).
Example:
// eventBus.js import emitter from 'tiny-emitter/instance' export default { $on: (...args) => emitter.on(...args), $once: (...args) => emitter.once(...args), $off: (...args) => emitter.off(...args), $emit: (...args) => emitter.emit(...args) }
This provides the same event emitter API as in Vue 2.
In most circumstances, using a global event bus for communicating between components is discouraged. While it is often the simplest solution in the short term, it almost invariably proves to be a maintenance headache in the long term. Depending on the circumstances, there are various alternatives to using an event bus:
provide
/inject
can also be used for long-distance communication between components. It can help to avoid 'prop drilling', where props need to be passed down through many levels of components that don't need those props themselves.
© 2013–present Yuxi Evan You
Licensed under the MIT License.
https://v3.vuejs.org/guide/migration/events-api.html