Skip to content

Commit d9430c2

Browse files
docs: add various improvements to the Events API migration guide (#1124)
1 parent 9554a83 commit d9430c2

File tree

1 file changed

+40
-19
lines changed

1 file changed

+40
-19
lines changed

src/guide/migration/events-api.md

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,77 +7,98 @@ badges:
77

88
## Overview
99

10-
`$on`, `$off` and `$once` instance methods are removed. Application instances no longer implement the event emitter interface.
10+
`$on`, `$off` and `$once` instance methods are removed. Component instances no longer implement the event emitter interface.
1111

1212
## 2.x Syntax
1313

14-
In 2.x, Vue instance could be used to trigger handlers attached imperatively via the event emitter API (`$on`, `$off` and `$once`). This was used to create _event hubs_ to create global event listeners used across the whole application:
14+
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:
1515

1616
```js
17-
// eventHub.js
17+
// eventBus.js
1818

19-
const eventHub = new Vue()
19+
const eventBus = new Vue()
2020

21-
export default eventHub
21+
export default eventBus
2222
```
2323

2424
```js
2525
// ChildComponent.vue
26-
import eventHub from './eventHub'
26+
import eventBus from './eventBus'
2727

2828
export default {
2929
mounted() {
30-
// adding eventHub listener
31-
eventHub.$on('custom-event', () => {
30+
// adding eventBus listener
31+
eventBus.$on('custom-event', () => {
3232
console.log('Custom event triggered!')
3333
})
3434
},
3535
beforeDestroy() {
36-
// removing eventHub listener
37-
eventHub.$off('custom-event')
36+
// removing eventBus listener
37+
eventBus.$off('custom-event')
3838
}
3939
}
4040
```
4141

4242
```js
4343
// ParentComponent.vue
44-
import eventHub from './eventHub'
44+
import eventBus from './eventBus'
4545

4646
export default {
4747
methods: {
4848
callGlobalCustomEvent() {
49-
eventHub.$emit('custom-event') // if ChildComponent is mounted, we will have a message in the console
49+
eventBus.$emit('custom-event') // if ChildComponent is mounted, we will have a message in the console
5050
}
5151
}
5252
}
5353
```
5454

5555
## 3.x Update
5656

57-
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
57+
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.
5858

5959
## Migration Strategy
6060

61-
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.
61+
[Migration build flag: `INSTANCE_EVENT_EMITTER`](migration-build.html#compat-configuration)
62+
63+
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.
64+
65+
### Root Component Events
66+
67+
Static event listeners can be added to the root component by passing them as props to `createApp`:
68+
69+
```js
70+
createApp(App, {
71+
// Listen for the 'expand' event
72+
onExpand() {
73+
console.log('expand')
74+
}
75+
})
76+
```
6277

63-
But the eventHub pattern can be replaced by using an external library implementing the event emitter interface, for example [mitt](https://github.com/developit/mitt) or [tiny-emitter](https://github.com/scottcorgan/tiny-emitter).
78+
### Event Bus
79+
80+
The event bus pattern can be replaced by using an external library implementing the event emitter interface, for example [mitt](https://github.com/developit/mitt) or [tiny-emitter](https://github.com/scottcorgan/tiny-emitter).
6481

6582
Example:
6683

6784
```js
68-
//eventHub.js
85+
// eventBus.js
6986
import emitter from 'tiny-emitter/instance'
7087

7188
export default {
7289
$on: (...args) => emitter.on(...args),
7390
$once: (...args) => emitter.once(...args),
7491
$off: (...args) => emitter.off(...args),
75-
$emit: (...args) => emitter.emit(...args),
92+
$emit: (...args) => emitter.emit(...args)
7693
}
7794
```
7895

7996
This provides the same event emitter API as in Vue 2.
8097

81-
These methods may also be supported in a future compatibility build of Vue 3.
98+
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:
8299

83-
[Migration build flag: `INSTANCE_EVENT_EMITTER`](migration-build.html#compat-configuration)
100+
* [Props](/guide/component-basics.html#passing-data-to-child-components-with-props) and [events](/guide/component-basics.html#listening-to-child-components-events) should be your first choice for parent-child communication. Siblings can communicate via their parent.
101+
* [Provide and inject](/guide/component-provide-inject.html) allow a component to communicate with its slot contents. This is useful for tightly-coupled components that are always used together.
102+
* `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.
103+
* Prop drilling can also be avoided by refactoring to use slots. If an interim component doesn't need the props then it might indicate a problem with separation of concerns. Introducing a slot in that component allows the parent to create the content directly, so that props can be passed without the interim component needing to get involved.
104+
* [Global state management](/guide/state-management.html), such as [Vuex](https://next.vuex.vuejs.org/).

0 commit comments

Comments
 (0)