Vue指令不触发方法

时间:2017-11-11 05:13:54

标签: vue.js vuejs2 vue-component

我有一个自定义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方法。

  • 事件 按预期在Vue devtools中发出。
  • Vue版本2.5.3

1 个答案:

答案 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?
      }
    });
  }
});