如图点击蓝色边框以外任意地方隐藏蓝色边框容器(不使用输入框的失焦事件)
实现思路:
获取到dom节点然后通过其contains方法来判断点击的地方是否为其子元素或其本身
原生js获取dom跟vue的$el都可以实现
也可以通过vue的this.$refs.showBoxRef.$el.contains()
注意事项:
1.如果不是在非必要的情况下可以使用v-show,这样就不会有dom渲染先后顺序的问题
2.记得在添加事件的时候传第三个参数阻止冒泡,不然点击本身的时候也会触发事件导致其无法显示,也可以在显示事件添加.stop来阻止冒泡
3.添加完事件记得要移除事件
4.一定主要注意在获取dom的时候看dom有没有渲染,不要在mounted之前的生命周期操作dom以及v-if值为false的元素
5.不要直接使用this.$refs['refName']否则就会报下面的错,示例代码通过this.$refs.showBoxRef.$el使用contains()也会报下面的错,因为获取dom的时候dom还没渲染即使加了$nextick()也会报错,但不影响功能,当然你也可以换一换写法,所以有强迫症的可以使用原生js获取dom即使获取不到也只会返回一个null而不会报错
Uncaught TypeError: this.$refs.showBoxRef.contains is not a function
at VueComponent.isClick
<template>
<div class="child-task-page">
<Button icon="ios-add" type="dashed" size="small" @click="add" ref="buttonRef">显示</Button>
<Row>
<Col
span="24"
v-if="showBox"
class="add-box"
ref="showBoxRef"
id="showBoxId"
>
<Checkbox v-model="curObj.check"></Checkbox>
<Input v-model="curObj.value" :border="false" placeholder="请输入" />
</Col>
</Row>
</div>
</template>
<script>
export default {
data() {
return {
showBox: false,
curObj: {
check: false,
name: "",
},
};
},
mounted () {
console.log(this.$el,'this');//直接this.$el可以获取到当前的dom节点,跟原生js获取的dom节点一样
console.log(this.$refs.buttonRef.$el,'showBoxRef');//this.$refs['refname']获取的是组件包含vue的一些属性,再.$el才是具体的dom节点
console.log(this.$refs.buttonRef.$el.contains,'contains');//获取到dom节点后就可以使用contains方法了
},
beforeDestroy() {
document.removeEventListener("click", this.isClick); //页面销毁的时候移除事件
},
methods: {
add() {
//往document身上添加点击事件,
// 参数一:事件类型
// 参数二:事件执行的函数
// 参数三:指定事件是否在捕获或冒泡阶段执行。
this.showBox = true;
this.$nextTick(() => {
// 加个this.$nextTick使dom更新后再执行获取dom的方法(在这里实际上没有用,改获取不到的还是获取不到,但不影响功能)
document.addEventListener("click", this.isClick, true);
});
},
isClick(e) {
console.log(
document.getElementById("showBoxId"),
'document.getElementById("showBoxId")'
);
let isSelf = document.getElementById("showBoxId"); //获取dom元素
if (isSelf) {
//判断一下dom元素有没有获取成功
if (!isSelf.contains(e.target)) {
//通过dom元素的contains方法传入目标元素,containsf方法返回一个布尔值
// 如果点击的是元素本身或者其子元素则返回true,否则返回false
this.showBox = false;
}
}
},
},
};
</script>
<style scoped lang="less">
.add-box {
display: flex;
border: 1px solid #2d8cf0;
border-radius: 3px;
padding: 10px;
}
</style>
mounted中的打印值: