检查组件是否附加了事件侦听器

Kas*_*tin 13 javascript vue.js vue-component vuejs2

假设有一些<Form>组件.它可以通过@cancel附加到它的事件监听器来调用,如果是这种情况,我想显示触发此事件的取消按钮.如果没有@cancel事件,则不应显示取消按钮.

有没有办法检查组件是否附加了事件监听器?

目前我这样做:

<template>
  <form>
    <button v-if="cancelEventPassed" @click="$emit('cancel')">Cancel</button>
  </form>
</template>
Run Code Online (Sandbox Code Playgroud)

并称之为:

<Form :cancelEventPassed="true" @cancel="handle_cancel" />
Run Code Online (Sandbox Code Playgroud)

<Form/>
Run Code Online (Sandbox Code Playgroud)

是否有可能在不使用任何其他属性的情况下实现这一目标cancelEventPassed

Ber*_*ert 22

当有一个侦听器附加到组件时,它们$listeners在组件的属性中可用.

您可以使用该属性来确定特定侦听器是否可用.例如,这是一个计算属性,用于检查是否存在cancel侦听器.

computed:{
  hasCancelListener(){
    return this.$listeners && this.$listeners.cancel
  }
}
Run Code Online (Sandbox Code Playgroud)

以下是组件中使用的示例.

console.clear()

Vue.component("CustomForm", {
  template:`
    <div>
      <h1>Custom Form</h1>
      <button v-if="hasCancelListener" @click="$emit('cancel')">I have a listener!</button>
    </div>
  `,
  computed:{
    hasCancelListener(){
      return this.$listeners && this.$listeners.cancel
    }
  },
})

new Vue({
  el: "#app",
  methods:{
    onCancel(){
      alert('canceled')
    }
  }
})
Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/vue@2.4.2"></script>
<div id="app">
  <custom-form @cancel="onCancel"></custom-form>
  <hr>
  <custom-form></custom-form>
</div>
Run Code Online (Sandbox Code Playgroud)


Pre*_*ola 15

在 Vue 3 中,该$listeners对象已被删除。侦听器现在是$attrs对象的一部分,并以 为前缀on

为了检查子组件中是否存在特定侦听器,您可以执行以下操作:

computed: {
  hasCancelListener() : boolean {
    return (this.$attrs && this.$attrs.onCancel) as boolean
  }
}
Run Code Online (Sandbox Code Playgroud)

子组件被称为:

<custom-form @cancel="onCancel"></custom-form>
Run Code Online (Sandbox Code Playgroud)

  • 请注意,如果您在“emits”属性中定义自定义事件,例如组件上存在“emits: ['click']”,则这不起作用,“$attrs.onClick”将是未定义的。这有点痛苦,因为这意味着您似乎无法检查自定义事件的侦听器是否存在。 (20认同)

Sim*_*mon 7

由于如果您像这样定义发射,则@prerak-sola的解决方案不起作用(正如 Adam Reis所指出的):

const emit = defineEmits<{
  (e: 'click', v: MouseEvent): void;
  (e: 'update:modelValue', v: MouseEvent): void;
}>();
Run Code Online (Sandbox Code Playgroud)

我发现,由于 vue 将所有 props 转换为一个对象,并且只是on在每个事件名称之前添加一个前缀,因此您可以检查属性(事件侦听器)是否在以下文件中定义vnode

const hasClickEventListener = computed(() => !!getCurrentInstance()?.vnode.props?.onClick);
const hasModelValueUpdateListener = computed(() => !!getCurrentInstance()?.vnode.props?.['onUpdate:modelValue']);
Run Code Online (Sandbox Code Playgroud)

然而,我在官方文档中找不到任何关于此的内容(并且它比使用困难得多useAttrs)。所以要谨慎使用。