javascript - 使用 clickoutside 指令动态增长下拉组件

标签 javascript vue.js

我有一个动态增长的下拉组件(其他下拉列表被添加到屏幕上)并且在组件内部,我使用了一个点击外部指令,当我在屏幕上只有 1 个下拉菜单时它工作得很好,但是当有多个下拉菜单时出现外部点击会发生冲突,导致无法打开下拉菜单。

我想在下拉菜单关闭时解决解除绑定(bind),但我不知道该怎么做。

指令-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 中,我收到一个数组,有时我只有一个项目,有时两个...

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

有什么帮助吗?

最佳答案

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

所以加一个

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

...在绑定(bind)函数的末尾

关于javascript - 使用 clickoutside 指令动态增长下拉组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57294417/

相关文章:

javascript - 如果用户使用的 FB 帐户与他注册的帐户不同,如何限制对 facebook API 的访问(通过 JS 对话框)

javascript - 如何在 react 中过滤唯一值?

javascript - 如何从 Flash 触发 JavaScript 函数?

vue.js - Vue3 : i18n plugin won't find localization in json file

javascript - 如何在使用 AnimatePresence 包装的 Next.js 页面中导航并滚动到具有 ID 的元素

javascript - 多个元素上的 jQuery 数学运算

vue.js - 单击 vue 组件中的保存按钮后如何关闭模式?

javascript - VueJS - 如何从 prop 评估花括号语法

javascript - 在 vue.js 模板中包含外部脚本

google-chrome - 为什么 Chrome DevTools 会显示我的 Vue 应用程序源代码的多个乱码版本?