假设有一些
<Form>
组件。可以使用附加的 @cancel
事件侦听器来调用它,如果是这种情况,我想显示触发此事件的取消按钮。如果没有 @cancel
事件,取消按钮应该不可见。
有没有办法检查组件是否附加了事件侦听器?
目前我做的是:
<template>
<form>
<button v-if="cancelEventPassed" @click="$emit('cancel')">Cancel</button>
</form>
</template>
并这样称呼它:
<Form :cancelEventPassed="true" @cancel="handle_cancel" />
都可以
<Form/>
是否可以在不使用任何其他属性(如
cancelEventPassed
)的情况下实现这一目标?
当组件附加了侦听器时,它们可以在组件的
$listeners
属性中使用。
您可以使用该属性来确定特定侦听器是否可用。例如,这是一个计算属性,用于检查
cancel
侦听器是否存在。
computed:{
hasCancelListener(){
return this.$listeners && this.$listeners.cancel
}
}
这是在组件中使用的示例。
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')
}
}
})
<script src="https://unpkg.com/[email protected]"></script>
<div id="app">
<custom-form @cancel="onCancel"></custom-form>
<hr>
<custom-form></custom-form>
</div>
在 Vue 3 中,
$listeners
对象已被删除。侦听器现在是 $attrs
对象的一部分,并且 带有 on
前缀。
为了检查子组件中是否存在特定侦听器,您可以执行以下操作:
computed: {
hasCancelListener() : boolean {
return (this.$attrs && this.$attrs.onCancel) as boolean
}
}
子组件称为:
<custom-form @cancel="onCancel"></custom-form>
因为 @prerak-sola 的解决方案不起作用,如果您像这样定义发射(如 所示) 亚当·里斯):
const emit = defineEmits<{
(e: 'click', v: MouseEvent): void;
(e: 'update:modelValue', v: MouseEvent): void;
}>();
我发现,由于 vue 将所有 props 转换为对象,并且只是在每个事件名称之前添加前缀
on
,因此您只需检查该属性(事件侦听器)是否在 vnode
中定义:
const hasClickEventListener = computed(() => !!getCurrentInstance()?.vnode.props?.onClick);
const hasModelValueUpdateListener = computed(() => !!getCurrentInstance()?.vnode.props?.['onUpdate:modelValue']);
但是,我在官方文档中找不到任何有关此内容的信息(并且它比使用
useAttrs
困难得多)。所以请谨慎使用。
this.$attrs.onCancel
Vue 3 删除了
$listeners
对象,而是侦听器将与带有 $attrs
前缀的 on..
对象分开。
https://v3-migration.vuejs.org/writing-changes/listeners-removed.html#overview
您可以这样检查监听器是否存在:
this._events['listener-name']
如果您在这里寻找 Vue 3
script setup
或 setup function
解决方案,您可以检查 attrs
函数中的 getCurrentInstance
键
<template>
<form>
<button @click="$emit('cancel')">Cancel</button>
</form>
</template>
<custom-form @cancel="onCancel"></custom-form>
onMounted(() => {
const instance = getCurrentInstance() // only available inside lifecycle hooks
console.log(instance?.attrs?.onCancel)
})
import {useListeners, computed} from 'vue';
const listeners = useListeners();
const hasCancelListener= computed(() => {
return typeof listeners['cancel'] !== 'undefined';
});
const thisInstance = getCurrentInstance();
const hasTaskClickedListener = computed(() => {
if (!thisInstance) return null;
return thisInstance.attrs?.onClicked;
});
说明:
this
与 vue 3 中的 getCurrentInstance()
相同onClick
、onDelete
等getCurrentInstance()
始终放在设置脚本上,除非你总是为 null(vue 无法看到其实例时的值)