我有一个自定义vue指令。
Vue.directive('click-outside', {
bind: function (el, binding, vnode) {
document.addEventListener(clickHandler, (event) => {
const clickedInsideDropdown = el.contains(event.target);
if (!clickedInsideDropdown && el.classList.contains(openClass)) {
vnode.context.$emit(binding.expression);
}
});
}
});
然后我使用下拉模板初始化它:
<template>
<div class="dropdown" :class="{ '-is-open': open }" v-click-outside="close">
<span @click="toggle">
<slot name="toggle"></slot>
</span>
<slot name="menu"></slot>
</div>
</template>
支持逻辑也按预期运作:
<script>
export default {
data: function () {
return {
open: false
}
},
methods: {
close: function () {
this.open = false;
console.log('close');
},
toggle: function () {
this.open = !this.open;
console.log('toggle');
}
}
}
</script>
当当前下拉列表打开并且单击其中没有任何项目时,该事件应该触发 - 这样做(控制台日志记录确认了这一点)。但是,$emit
由于某种原因未触发close
方法。
2.5.3
答案 0 :(得分:0)
向Linus Borg致信answered my question for me on the forum。只是错误地理解了事件的目的。
事件通常用于从子组件到父组件进行通信,因此在组件中触发事件“关闭”将不会在该组件中运行该名称的方法。
如果你想要,你必须实际注册一个监听器:
created () {
this.$on('close', this.close /*the name of the method to call */)
}
但是,在您的情况下,这不是必需的。您已经将close方法传递给指令,因此您可以直接运行它:
Vue.directive('click-outside', {
bind: function (el, binding, vnode) {
document.addEventListener(clickHandler, (event) => {
const clickedInsideDropdown = el.contains(event.target);
if (!clickedInsideDropdown && el.classList.contains(openClass)) {
binding.value()
// alternartively, you could also call the method directly on the instance, no need for an event:
vnode.context.[expression]()
// but that wouldn't really be elegant, agreed?
}
});
}
});