一、在开发popover遇到的问题
我需要点击按钮弹出气泡,点击页面其他地方气泡消失,我们首先就想到了下面代码
点击按钮时给pop一个条件语句,如果visible是true那么就给document一个事件监听,点击网页就会把visible变成false
<template>
<div class="popover" @click="pop" v-if="visible">
</div>
</template>
<script>
export default {
data() {
return { visible: false };
},
methods: {
pop() {
this.visible = !this.visible;
if (this.visible === true) {
document.addEventListener("click", ()=>{
this.visible = !this.visible
});
}
}
}
}
};
</script>二、第一个问题-点击按钮都无法做到出现气泡
此时连点击按钮都无法做到出现气泡
因为监听函数,只会在冒泡阶段触发。当div触发pop时添加监听函数,click继续冒泡,document触发了它的回调函数。结果就是visible没变
pop() {
this.visible = !this.visible;
if (this.visible === true) {
setTimeout(() => {
function outClick(){
this.visible = false;
}
document.addEventListener("click", outClick);
},0);
}
}加入异步处理即可,把事件监听推迟到click冒泡结束
三、第三个问题-点击页面任何地方无法取消气泡
此时依然做不到点击页面任何地方取消气泡。
addEventListener监听函数内部的this指向事件所在的对象,即document
document.addEventListener("click", outClick.bind(this));problem solved!
四、第四个问题-第三次点击没有任何反应
初步判断是由于document的监听函数没有被移除,所以第三次点击按钮(第一次二次分别弹出和移除)同时触发两个监听函数。
我们加一个 removeEventListener 理论上就可以了
methods: {
pop() {
this.visible = !this.visible;
if (this.visible === true) {
setTimeout(() => {
function outClick(){
this.visible = false;
document.removeEventListener("click", outClick.bind(this));
}
document.addEventListener("click", outClick.bind(this));
},0);
}
}
}结果发现不行,是因为bind() 方法创建的是一个新的函数, removeEventListener 的不是同一个回调
methods: {
pop() {
this.visible = !this.visible;
if (this.visible === true) {
setTimeout(() => {
const outClick = () => {
this.visible = false;
document.removeEventListener("click", outClick);
};
document.addEventListener("click", outClick);
}, 0);
}
}
}箭头函数固定this
problem solved!