前言
在前端开发中,我们常常会遇到需要检测用户是否点击了某个元素外部的场景,比如弹出框在用户点击外部时需要关闭。接下来我们来封装一个 clickOutside 自定义指令
代码解析 Vue3
import { Directive } from 'vue';
// 定义 ClickOutside 指令类型
const clickOutside: Directive<HTMLElement, () => void> = {
// 当指令绑定到元素并插入到 DOM 中时调用
mounted(el: HTMLElement, binding) {
// 定义事件处理函数,类型注解表明它接收一个 MouseEvent 类型的参数
const handler = (event: MouseEvent) => {
// 判断点击的目标元素是否不在绑定指令的元素内部
if (!el.contains(event.target as Node)) {
// 调用绑定指令时传入的回调函数
binding.value();
}
};
// 给 document 添加 click 事件监听器
document.addEventListener('click', handler);
// 将事件处理函数存储在元素的自定义属性上,方便后续移除监听器
el.__clickOutsideHandler = handler;
},
// 当指令所绑定的元素从 DOM 中移除时调用
unmounted(el: HTMLElement) {
// 移除之前添加到 document 上的 click 事件监听器
document.removeEventListener('click', el.__clickOutsideHandler);
// 删除元素上存储的事件处理函数属性
delete el.__clickOutsideHandler;
},
};
export default clickOutside;
使用示例 Vue3
<template>
<div class="index">
<div class="box">
<div>举个例子</div>
<div class="more" @click="moreClick">···</div>
<div
class="more-box"
v-if="moreShow"
v-click-outside="handleClickOutside"
>
<div>干嘛呢</div>
<div>干嘛呢</div>
<div>干嘛呢</div>
<div>干嘛呢</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, Directive } from "vue";
const moreShow = ref(false);
function moreClick(event: any) {
console.log("更多被戳了一下");
moreShow.value = !moreShow.value;
event.stopPropagation();
}
function handleClickOutside() {
moreShow.value = false;
}
</script>
<style scoped lang="scss">
.index {
overflow: hidden;
}
.box {
width: 300px;
height: 160px;
border: 1px solid #00000055;
border-radius: 10px;
padding: 10px;
margin: 100px;
position: relative;
}
.more {
cursor: pointer;
text-align: center;
width: 30px;
height: 30px;
position: absolute;
top: 10px;
right: 10px;
}
.more-box {
position: absolute;
right: -20px;
width: 90px;
border: 1px solid #00000055;
border-radius: 10px;
background: #ffffff;
padding: 10px 0px;
div {
line-height: 36px;
text-align: center;
}
}
</style>
vue2 写法
const clickOutside = {
// 当指令第一次绑定到元素时调用,在这里进行初始化设置
bind: function (el, binding) {
// 定义事件处理函数,用于处理 document 的 click 事件
const handler = function (event) {
// 判断点击的目标元素是否不在绑定指令的元素内部
if (!el.contains(event.target)) {
// 调用绑定指令时传入的回调函数
binding.value();
}
};
// 给 document 添加 click 事件监听器
document.addEventListener('click', handler);
// 将事件处理函数存储在元素的自定义属性上,方便后续移除监听器
el.__clickOutsideHandler = handler;
},
// 当指令与元素解绑时调用,在这里进行清理工作
unbind: function (el) {
// 移除之前添加到 document 上的 click 事件监听器
document.removeEventListener('click', el.__clickOutsideHandler);
// 删除元素上存储的事件处理函数属性
delete el.__clickOutsideHandler;
}
};
export default clickOutside;