本文是基于vue3的Element Plus版本。vue2的Element UI是否可用有待验证!
项目中经常会有一些自己的弹层,需要通过点击其他的地方之后关闭这个弹层。所以就衍生出了vClickOutside的方法。
一、最常用的情况
1、引入ClickOutside
import { ClickOutside as vClickOutside } from "element-plus";
2、在对象的Dom元素中添加对应的事件
<div class="smallDom" v-click-outside="outsideClick">里面</div>
3、在函数中写自己的逻辑
const outsideClick = (e) => {
console.log('点击的是其他的元素,不是自身')
}
4、完整示例代码
<template>
<div id="test">
<div id="bigDom">
<div class="smallDom" v-click-outside="outsideClick">里面</div>
</div>
</div>
</template>
<script setup>
import { ClickOutside as vClickOutside } from "element-plus";
const outsideClick = (e) => {
console.log('点击的是其他的元素,不是自身')
}
</script>
<style lang="css" scoped>
#bigDom {
width: 500px;
height: 600px;
border: 1px solid black;
}
.smallDom {
width: 100%;
height: 200px;
border: 1px solid red;
}
</style>
二、添加一个忽略DOM
但是在开发中经常遇到一种情况就是。当我们点击本DOM元素之后的一个元素,也是希望算点击本DOM元素之内,也就是点击另一个元素也希望不触发这个outsideClick函数。那么我们需要这么操作;
1、在自定义指令的时候,后面添加一个:[ignoreDomRef],数组中是需要添加的忽略元素的ref对象;
<div class="smallDom" v-click-outside:[ignoreDom]="outsideClick">里面</div>
2、完整示例代码
<template>
<div id="test">
<div id="bigDom">
<div class="smallDom" v-click-outside:[ignoreDom]="outsideClick">里面</div>
<div class="smallDom" ref="ignoreDom"></div>
</div>
</div>
</template>
<script setup>
import { ClickOutside as vClickOutside } from "element-plus";
import { ref } from "vue";
var ignoreDom = ref()
const outsideClick = (e) => {
console.log('点击的是其他的元素,不是自身')
}
</script>
<style lang="css" scoped>
#bigDom {
width: 500px;
height: 600px;
border: 1px solid black;
}
.smallDom {
width: 100%;
height: 200px;
border: 1px solid red;
}
</style>
3、遇到的问题,不能添加多个忽略Dom
但是这里有个问题,就是这个元素只能添加一个,如果我还有一个元素,也想添加到这里的忽略dom元素,不生效;(如果大家知道有什么方法,也可以与博主交流)
<!--此代码不生效-->
<div class="smallDom" v-click-outside:[ignoreDom,ignoreDom2]="outsideClick">里面</div>
三、添加多个忽略DOM
1、通过v-click-outside的$event解决忽略多个Dom
因为可以获取到点击的事件的$event,所以可以用来判断是不是需要执行outsideClick中的内容。查看$event的内容;利用当前点击的target确认是不是在忽略的Dom元素内,在判断是不是需要执行对应的方法;
这里用到一个js的contains的方法,用来判断,一个元素是否包含在另一个元素中。
2、完整示例代码
<template>
<div id="test">
<div id="bigDom">
<div class="smallDom" v-click-outside="outsideClick">里面</div>
<div class="smallDom" ref="ignoreDom"><p>ignoreDom的子元素</p></div>
<div class="smallDom" ref="ignoreDom2"><p>ignoreDom2的子元素</p><p>ignoreDom2的子元素</p></div>
</div>
</div>
</template>
<script setup>
import { ClickOutside as vClickOutside } from "element-plus";
import { ref, onMounted } from "vue";
var ignoreDom =ref(),ignoreDom2 = ref();
const outsideClick = (e) => {
console.log(e);
if (
ignoreDom.value.contains(e.target) ||
ignoreDom2.value.contains(e.target)
) {
console.log("点击的是忽略的元素,或其子元素");
} else {
console.log("点击的是其他的元素");
}
};
</script>
<style lang="css" scoped>
#bigDom {
width: 500px;
height: 600px;
border: 1px solid black;
}
.smallDom {
width: 100%;
height: 200px;
border: 1px solid red;
}
</style>
以上就能完美的解决点击其他地方关闭弹窗,并且添加多个忽略Dom的完整功能;