1 需求分析
在 Vue 开发中,使用自定义组件或者第三方ui组件遇到需要实现点击弹窗以外区域关闭弹窗的需求时
例如:当用户打开一个弹窗或气泡框时,希望点击弹窗以外的区域能够关闭弹窗。这个需求在很多场景下都非常实用,比如用户在查看详情页面时,弹出一个模态框,当用户点击模态框以外的区域时,能够关闭模态框并返回上一页等
2 实现思路
-
在 Vue 组件中,使用
v-if
或v-show
指令创建弹窗或使用UI组件库弹窗
来控制弹窗的显示和隐藏 -
给整个页面添加一个点击事件监听器,当用户点击页面上除弹窗以外的区域时,关闭弹窗。
-
当用户点击弹窗时,阻止事件冒泡,防止点击弹窗内部区域时误关闭弹窗。
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
指令来控制显示和隐藏。当showModal
为true
时,弹窗显示;当showModal
为false
时,弹窗隐藏
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"],防止弹窗打不开,然后判断当前是否显示弹窗,并且点击的目标元素是否不包含在弹窗内部。如果满足条件,则关闭弹窗