vue.jsvuejs3vue-script-setup

VueJS: Can a child component observe if a parent component has defined its event handler


given a child component Foo.vue

<template>
  ...
  <button @click="emit('bah', ...)">...</button>
  ...
</template>

<script setup>
const emit = defineEmits(['bah'])
...
</script>

is it possible to test within Foo.vue if the parent has actually defined @bah? e.g.

...
<div>
<Foo @bah="doSomething"/>
</div>
...

vue used to have a $listeners array and I assumed the process would be similar to the way one can test if the parent component has used slots with useSlots() but I'm struggling to find much beyond a conversation on a related subject here. Indeed: the docs here suggests that listeners have been merged into $attrs, but when I investigate useAttrs() onMounted I don't see any listeners.

<script setup>
import {onMounted, useAttrs} from 'vue'

const attrs = useAttrs()

onMounted(() => {
  console.log(attrs) // no attrs present
})
...

[edit] documentation suggests that defineEmits clears useAttrs (see earlier references). But does that mean you'd have to manually define event handlers instead to test if they're defined by the parent component?


Solution

  • Event listeners are translated to camel-cased on... props internally. They may not be available through regular props object, it's possible to access them on a vnode:

    const rawProps = getCurrentInstance().vnode.props;
    
    console.assert(rawProps.onBah);