vue中实现点击弹窗、气泡框以外区域关闭弹窗气泡框

1,201 阅读3分钟

1 需求分析

在 Vue 开发中,使用自定义组件或者第三方ui组件遇到需要实现点击弹窗以外区域关闭弹窗的需求时

例如:当用户打开一个弹窗或气泡框时,希望点击弹窗以外的区域能够关闭弹窗。这个需求在很多场景下都非常实用,比如用户在查看详情页面时,弹出一个模态框,当用户点击模态框以外的区域时,能够关闭模态框并返回上一页等

2 实现思路

  1. 在 Vue 组件中,使用v-ifv-show指令创建弹窗或使用UI组件库弹窗来控制弹窗的显示和隐藏

  2. 给整个页面添加一个点击事件监听器,当用户点击页面上除弹窗以外的区域时,关闭弹窗。

  3. 当用户点击弹窗时,阻止事件冒泡,防止点击弹窗内部区域时误关闭弹窗。

3 具体实现

1.创建一个 Vue 页面,实现一个简易打开弹窗功能

<template>
  <div>
    <button class="my-button" @click="showModal = true">打开弹窗</button>
    <div v-if="showModal" class="modal">
      <div class="modal-content">
        <h2>弹窗内容</h2>
        <p>这是一个弹窗,可以在这里添加任何内容。</p>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      showModal: false
    };
  }
};
</script>
<style>
.modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
}
.modal-content {
  background-color: white;
  padding: 20px;
  border-radius: 5px;
}
</style>

在这个页面中,点击按钮可以打开弹窗。弹窗使用v-if指令来控制显示和隐藏。当showModaltrue时,弹窗显示;当showModalfalse时,弹窗隐藏

image-20240930120247613.png

2.阻止事件冒泡

当点击弹窗内部区域时,需要阻止事件冒泡,防止误关闭弹窗。可以通过在弹窗内部的元素上添加@click.stop指令或通过点击事件回调来实现

vue指令

<template>
  <div>
    <button class="my-button" @click="showModal = true">打开弹窗</button>
    <div v-if="showModal" class="modal">
      <div class="modal-content" @click.stop>
        <h2>弹窗内容</h2>
        <p>这是一个弹窗,可以在这里添加任何内容。</p>
      </div>
    </div>
  </div>
</template>

事件回调:

<template>
  <div>
    <button class="my-button" @click="showModal = true">打开弹窗</button>
    <div v-if="showModal" class="modal">
      <div class="modal-content" @click="handleClick">
        <h2>弹窗内容</h2>
        <p>这是一个弹窗,可以在这里添加任何内容。</p>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  methods: {
    handleClick(event) {
      event.stopPropagation();
    }
  }
};
</script>

3.添加页面点击事件监听器(关键)

给整个页面添加一个点击事件监听器,当点击页面上除弹窗以外的区域时,关闭弹窗。可以在mounted生命周期钩子中添加事件监听器,并在beforeDestroy生命周期钩子中移除事件监听器

<script>
export default {
  data() {
    return {
      showModal: false
    };
  },
  mounted() {
    document.addEventListener('click', this.handleOutsideClick);
  },
  beforeDestroy() {
    document.removeEventListener('click', this.handleOutsideClick);
  },
  methods: {
    handleOutsideClick(event) {
      // 阻止触发按钮区域的点击事件,否则将打不开弹窗
      if (event.target.classList.contains('my-button')) {
        return
      }
      // 打开弹窗并且点击了其他区域,关闭弹窗
      if (this.showModal && !event.target.classList.contains('modal-content')) {
        this.showModal = false;
      }
    }
  }
};
</script>

handleOutsideClick方法中,先排除点击打开当前弹窗的按钮区域[class="my-button"],防止弹窗打不开,然后判断当前是否显示弹窗,并且点击的目标元素是否不包含在弹窗内部。如果满足条件,则关闭弹窗

4 效果预览

111.gif