Unable to listen for event handler in $attrs when event is defined in $emits
Vue version
3.2.47
Link to minimal reproduction
https://codesandbox.io/s/late-voice-pj0bhv?file=/src/components/HelloWorld.vue
Steps to reproduce
- Create a child component that listens for an event using
this.$attrs
/useAttrs()
and renders a button conditionally depending on whether an event listener is present from the parent - Define the event in
this.$emits
/defineEmits
- The button doesn't render
- Remove the event from
this.$emits
/defineEmits
- The button does render
- Causes a type error when used within a typescript project
What is expected?
- The button should render because an event listener is present on the parent
What is actually happening?
- The button doesn't render if the event is defined in emits
System Info
System:
OS: Linux 5.19 Ubuntu 22.04.2 LTS 22.04.2 LTS (Jammy Jellyfish)
CPU: (16) x64 Intel(R) Core(TM) i7-10875H CPU @ 2.30GHz
Memory: 49.27 GB / 62.41 GB
Container: Yes
Shell: 5.1.16 - /bin/bash
Binaries:
Node: 16.19.0 - ~/.nvm/versions/node/v16.19.0/bin/node
Yarn: 1.22.19 - ~/.nvm/versions/node/v16.19.0/bin/yarn
npm: 8.19.3 - ~/.nvm/versions/node/v16.19.0/bin/npm
Browsers:
Chrome: 110.0.5481.177
Firefox: 112.0
npmPackages:
vue: ^3.2.47 => 3.2.47
Any additional comments?
The demo contains a couple of examples; one where the button renders (when the event is removed from emits) and two where the button doesn't render (event is defined in emits).
Surely this isn't expected behaviour?
It is. just like declared props, declared events are not part of attrs
. Otherwise, these events would all automatically be passed onto the component's root element as fallthrough attributes.
Currently though, unlike for props, there is no dedicated api to check wether a listener for a declared event has been passed to a component.
Valid alternative: declare the event as a prop instead - event listeners are, internally, just props with a on[A-Z]
naming:
props: {
msg: String,
onClick: Function,
onChange: Function,
}
Then you can use v-if="onClick"
etc.
Other alternative would be to not declare the events at all (and use inheritAttrs: false
if they should not fall through), then they will be part of attrs
.
Also related feature request: #7719