首页 > 解决方案 > 使用 clickoutside 指令动态增长的下拉组件

问题描述

我有一个动态增长的下拉组件(其他下拉列表已添加到屏幕),在组件内部,我使用 click outside 指令,当我在屏幕上只有 1 个下拉列表时它可以正常工作,但是当出现多个下拉列表时单击外部会冲突,导致没有下拉菜单打开。

我想在下拉列表关闭时解决解除绑定问题,但我不知道该怎么做。

指令-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;
  },
};

下拉组件.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我收到一个数组时,有时我只有一个项目,有时是两个......

简历:当我只有一个下拉列表时,效果很好,但是当我有多个点击外部冲突时,我认为解决该问题的方法是在关闭下拉列表时取消绑定外部点击,并在打开时绑定,但我不知道该怎么做。

有什么帮助吗?

标签: javascriptvue.js

解决方案


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

所以添加一个

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

...在绑定函数的末尾


推荐阅读