具有clickoutside指令的动态增长下拉组件

时间:2019-07-31 15:36:18

标签: javascript vue.js

我有一个动态增长的下拉菜单组件(其他下拉菜单已添加到屏幕上),并且在该组件内部,我使用了click outside指令,当我在屏幕上只有1个下拉菜单时,它可以正常工作,但是当多个下拉菜单有效时似乎外部点击会发生冲突,因此不会打开任何下拉列表。

我想在下拉菜单关闭时解决 unbind ,但是我不知道该怎么做。

directive-clickoutside.js

export default {
  bind(el, binding, vNode) {
    console.log('bind');
    // Provided expression must evaluate to a function.
    if (typeof binding.value !== 'function') {
      const compName = vNode.context.name;
      let warn = `[Vue-click-outside:] provided expression '${binding.expression}' is not a function, but has to be`;
      if (compName) { warn += `Found in component '${compName}'` }

      console.warn(warn);
    }
    // Define Handler and cache it on the element
    // eslint-disable-next-line prefer-destructuring
    const bubble = binding.modifiers.bubble;
    const handler = (e) => {
      if (bubble || (!el.contains(e.target) && el !== e.target)) {
        binding.value(e);
      }
    };
    // eslint-disable-next-line no-underscore-dangle
    el.__vueClickOutside__ = handler;

    // add Event Listeners
    document.addEventListener('click', handler);
  },

  unbind(el, binding) {
    // Remove Event Listeners
    console.log('unbind');
    // eslint-disable-next-line no-underscore-dangle
    document.removeEventListener('click', el.__vueClickOutside__);
    // eslint-disable-next-line no-underscore-dangle
    el.__vueClickOutside__ = null;
  },
};

DropdownComponent.vue

<template>
    <div v-for="type in criticalityTypes" :key="type" id="users-list-form" class="users-list-form neo-col" :class="type">
      <div class="neo-form-select neo-form-select__filter"
         v-click-outside="currentOpenType ? closeList : doNothing"
         :class="{'neo-is-open': open[type]}">
        <input type="text"
               class="neo-form-field neo-form-select__field"
               @click="showList(type)"
               :placeholder="inputPlaceholder(type)"
               v-model="searchQuery[type]">
        <span class="neo-form-select__icon" @click="showList(type)"></span>
        <div class="neo-form-select__options">
        // OMMITED CODE
        </div>
      </div>
    </div>
</template>

<script>
import clickOutside from '../../../../directives/clickoutside.js';

export default {
  name: 'ConfigUsersNotification',
  props: [
    'data',
    'criticalityTypes',
  ],
  directives: {
    clickOutside,
  },
  data() {
    return {
      open: {
        CRITICALITY_HIGH: false,
        CRITICALITY_MEDIUM: false,
        CRITICALITY_LOW: false,
      },
      searchQuery: {
        CRITICALITY_HIGH: '',
        CRITICALITY_MEDIUM: '',
        CRITICALITY_LOW: '',
      },
      currentOpenType: '',
    };
  },
  methods: {
    showList(type) {
      if (!this.open[type]) {
        this.open[type] = !this.open[type];
      }
      this.currentOpenType = type;
      this.closeOthers(type);
      if (this.data.length === 0) {
        this.$emit('loadUsers');
      }
    },
    closeList() {
      this.open[this.currentOpenType] = false;
      this.currentOpenType = '';
    },
    closeOthers(type) {
      Object.keys(this.open).forEach((item) => {
        if (item !== type) {
          this.open[item] = false;
        }
      });
    },
  },
};
</script>

criticalityTypes中,我收到一个数组,有时我只有一个,有时是两个...

简历:当我仅查看一个下拉菜单时,效果很好,但是当我看到多个下拉菜单时,外部点击冲突, 我想解决该问题的方法是,在关闭下拉菜单时取消外部的单击绑定,并在打开时进行绑定,但是我不知道该怎么做。

有帮助吗?

1 个答案:

答案 0 :(得分:1)

防止元素上的点击冒泡到document上,将阻止它们触发页面中任何其他元素的点击外功能。

因此添加

el.addEventListener('click', function(e) { e.stopPropagation(); }); 

...在绑定函数的末尾