首页 > 解决方案 > 隐藏文档单击时的所有弹出框-单击的除外(事件顺序错误)

问题描述

我正在使用 Vue.js,并且我有一个包含天数的日历组件。当您单击一天时,它会显示它是弹出框。我正在尝试这样做,以便如果您单击文档中的任何位置,它会隐藏所有弹出窗口。但它不应该隐藏我刚刚打开的那个。

我为文档单击添加了一个事件侦听器,但它在Day 组件的@click事件之后触发。这意味着它会显示当天的弹出框,然后立即隐藏所有弹出框。但它应该首先隐藏所有弹出框,然后才显示 Day 的弹出框。

HTML

<div id="app">
    <calendar-month-view>
        <day></day>
        <day></day>
        <day></day>
    </calendar-month-view>
</div>

我的一天组件

export default {

    template: `
        <div @click="isVisiblePopover = !isVisiblePopover">
            <popover v-show="isVisiblePopover" />
        </div>
    `,

    components: {
        Popover
    },

    data() {
        return {
            isVisiblePopover: false
        }
    },

    mounted() {
        $(document).click(event => {
            EventBus.$emit('popover-opened')
        });

        EventBus.$on('popover-opened', () => {
            this.isVisiblePopover = false
        });
    }
};

标签: javascriptvue.js

解决方案


实现这一点的最简单方法是实现一种布局,放在弹出框后面,作为Popover组件的一部分,占据 100% 的屏幕(不可见,或者可能具有某种不透明度)。然后,您应该处理当单击背面布局并且未单击对话框本身时弹出框也将关闭的问题。它比处理整个文档中的点击更简单(也处理弹出点击!)。

这里有一个弹出组件应该是什么样子的示例:

Vue.component('popover', {
  template: `
    <div id="popover-layout" @click="layoutClicked($event)">
      <div id="popover-dialog" ref="popoverDialog">
        Popover dialog
      </div>
    </div>
  `,
  methods: {
    layoutClicked(event) {
      if(event.target !== this.$refs.popoverDialog) {
        console.log('Close popover!')
      }
    }
  }
});


var vm = new Vue({
  el: '#app'
});
#popover-layout {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  opacity: 0.3;
  background: silver;
}

#popover-dialog {
  width: 200px;
  height: 150px;
  position: absolute;
  top: 50%;
  left: 50%;
  margin-top: -75px;
  margin-left: -100px;
  border: 1px solid black;
  background: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <popover></popover>
</div>


推荐阅读