这可能是过于复杂的方法,但已经完成了。我想要的是从指令发出自定义事件,并通过插槽在父组件中监听该事件。
但是重点 -> 模型项目 = https://codesandbox.io/s/kind-cray-76ytzl?file=/src/directives/input-control.vue
在“input-control.vue”中,我尝试发出名为“vcOnChange”的自定义事件
// Debounce might be improved for better user experience
el.addEventListener('input', _.debounce(() => {
console.log('vnode:', vnode);
const validationResult = vnode.formControl.validate();
// This is tricky part
emit(vnode, 'vcOnChange', { 'validators': validationResult});
vnode.context.$emit('vcOnChange', { 'validators': validationResult});
}, 200));
“emit”函数看起来或多或少像这样:
const emit = (vnode, name, data) => {
var handlers = (vnode.data && vnode.data.on) || (vnode.componentOptions && vnode.componentOptions.listeners);
if (handlers && handlers[name]) {
handlers[name].fns(data);
}
}
这不是棘手的部分。当通过插槽导入带有我的自定义指令的组件时,我想从父组件中监听此事件。
所以在虚拟示例中我有这样的东西:
<custom-input>
<template v-slot:label>
Input label
</template>
<input type="text" novalidate v-form-control="inputFC" placeholder="placeholder">
<template v-slot:hint>
Some random hint
</template>
<template v-slot:errors>
some random errors
</template>
</custom-input>
唯一可行的解决方案是使用 vnode 上下文,但是它会产生问题,即哪个事件被发送到与指令绑定的所有元素。老实说,我不知道为什么会发生这种情况,而且我找不到任何替代解决方案。当组件有多个命名插槽时,有没有办法从默认插槽监听自定义 $emit?
首先,事件被发送到与该指令绑定的所有元素的原因可能是因为您使用的是 vnode.context.$emit('vcOnChange', { 'validators':validationResult });发出事件。
这会在 vnode 的上下文中发出事件,该事件可能不特定于指令的当前实例。相反,您应该使用 this.$emit('vcOnChange', { 'validators':validationResult }); 在当前实例上发出事件。
您可以采用的方法是使用道具和事件
在您的指令中:
const emit = (name, data) => {
EventBus.$emit(name, data);
}
在您的父组件中:
created() {
EventBus.$on('vcOnChange', (data) => {
// Handle the event here
});
}
不要忘记创建事件总线:
import Vue from 'vue';
export const EventBus = new Vue();
记住在需要使用的地方导入EventBus。