【问题标题】:how to hide dropdown menu if we click outside the menu in vuejs如果我们在 vuejs 中单击菜单外部,如何隐藏下拉菜单
【发布时间】:2018-02-12 19:20:52
【问题描述】:

我在 vuejs 中使用 dropdown 菜单组件来制作正常的下拉菜单。 我的代码是 dropdown 组件是:

<template>
    <span class="dropdown" :class="{shown: state}">
        <a href="#" @click.prevent="toggleDropdown" class="dropdown-toggle">toggle menu</a>
            <div class="dropdown-menu" v-show="state">
                <ul class="list-unstyled">
                    <slot></slot>
                </ul>
            </div>
        </transition>
    </span>
</template>

<script>
export default {
    name: 'dropdown',
    data () {
        return {
            state: false
        }
    },
    methods: {
        toggleDropdown (e) {
            this.state = !this.state;
        }
    }
}
</script>

现在我正在使用模板中的以下代码在我的VUE 应用程序中的各个位置导入dropdown 组件

<dropdown>
    <li>
         Action
    </li>
</dropdown>

现在效果很好,但我希望同时只有一个下拉菜单处于活动状态。

我做了一些研究,发现我可以使用像https://github.com/davidnotplay/vue-my-dropdown 这样的插件,但我不想使用它。同样,我还研究了上述示例的工作原理,但我想以这样一种方式实现此下拉功能,即我的dropdown 组件将处理与下拉相关的所有事件。 那么您能帮我实现这一目标吗?

【问题讨论】:

    标签: javascript drop-down-menu vue.js vuejs2 vue-component


    【解决方案1】:

    我知道这是一个相当老的问题,但我认为在没有任何外部插件的情况下做到这一点的最佳方法是将点击监听器添加到挂载的生命周期钩子(并在 beforeDestroy 钩子上删除它)并过滤组件上的点击,以便它只有在外面点击时才会隐藏。

    <template>
        <span class="dropdown" :class="{shown: state}">
          <a href="#" @click.prevent="toggleDropdown" class="dropdown-toggle">toggle menu</a>
                <div class="dropdown-menu" v-show="state">
                    <ul class="list-unstyled">
                        <slot></slot>
                    </ul>
                </div>
            <transition/>
        </span>
    </template>
    
    <script>
    export default {
      name: 'dropdown',
      data () {
        return {
          state: false
        }
      },
      methods: {
        toggleDropdown (e) {
          this.state = !this.state
        },
        close (e) {
          if (!this.$el.contains(e.target)) {
            this.state = false
          }
        }
      },
      mounted () {
        document.addEventListener('click', this.close)
      },
      beforeDestroy () {
        document.removeEventListener('click',this.close)
      }
    }
    </script>
    

    【讨论】:

    • 我以前用过这种方法。放入 mixin 或指令时效果很好。插件越少越好,尤其是当它们如此简单时。
    【解决方案2】:

    看看 vue-clickaway.(Link)

    有时您需要检测元素外部的点击(关闭模式窗口或隐藏下拉选择)。没有原生事件,而且 Vue.js 也不会覆盖你。这就是 vue-clickaway 存在的原因。在进一步阅读之前,请先查看演示。

    【讨论】:

    • @Shubham 它可能会解决问题,但我想尽量减少对任何外部组件/插件/资源的依赖。无论如何,我会尝试实现类似的功能,谢谢
    【解决方案3】:

    在 Vue 3 中,以下应该可以工作

    请注意,下拉触发器和下拉内容上的@click.stop 会阻止文档事件执行关闭功能。

    <template>
      <div class="dropdown" :class="{'is-active': dropdown.active.value}">
        <div class="dropdown-trigger">
          <button class="button" @click.stop="dropdown.active.value = !dropdown.active.value">
            Toggle
          </button>
        </div>
        <div class="dropdown-menu" role="filter">
          <div class="dropdown-content" @click.stop>
            <!-- dropdown items -->
          </div>
        </div>
      </div>
    </template>
    
    <script>
    
    import { defineComponent, ref, onMounted, onBeforeUnmount } from "vue";
    
    export default defineComponent({
      name: "Dropdown",
      setup(){
        const dropdown = {
          active: ref(false),
          close: () => {
            dropdown.active.value = false
          }
        }
    
        onBeforeUnmount(() => {
          document.removeEventListener('click', dropdown.close)
        })
    
        onMounted(() => {
          document.addEventListener('click', dropdown.close)
        })
    
        return {
          dropdown
        }
      }
    })
    
    </script>
    

    这个例子使用bulma,但当然你不需要。

    【讨论】:

      【解决方案4】:

      您可以使用blur 事件,例如如果你添加一个方法:

      close() {
          setTimeout(() => {
              this.state = false;
          }, 200);
      }
      

      并为您的链接设置blur 事件:

      <a href="#" @click.prevent="toggleDropdown" @blur="close">toggle menu</a>
      

      然后,当您的切换链接失去焦点时,下拉菜单将被隐藏。 setTimeout 是必要的,因为 Javascript 点击事件发生在模糊之后,这将导致您的下拉链接不可点击。要解决此问题,请稍微延迟菜单隐藏。

      【讨论】:

      • 是的,但这可能不是完美的解决方案。此外,我认为我们必须将模糊事件绑定到父包装器,因为用户可能需要一些毫秒才能从下拉菜单中选择操作
      猜你喜欢
      • 2019-10-27
      • 1970-01-01
      • 2017-03-01
      • 2022-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-08
      相关资源
      最近更新 更多