当我们在开发选择器组件的时候,一定会遇到一个问题,点击选项时,让下拉框隐藏,无法触发选项的点击事件选中选项
以下是两种解决方案,mark下来,下次你女朋友问你的时候,直接那这篇笔记给她看
使用input的focus和blur事件控制下拉框显示隐藏
在使用 input 的 focus 和 blur 事件控制下拉框的显示隐藏时,如果点击选项时,会先触发 input 的 blur 事件让下拉框隐藏,隐藏后无法触发选项的点击事件
<template>
<div>
<input @focus="handleFocus" @blur="handleBlur">
<ul>
<li @click="handleClick"></li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
show: !1
}
},
methods: {
handleFocus() {
this.show = true
}
handleBlur() {
this.show = false
}
handleClick() {
console.log('click')
}
}
}
</script>
解决方式
将隐藏的操作用setTimeout延迟执行,也就是将该操作放入宏任务中,执行完点击事件上的主代码再去执行隐藏的操作
handleBlur() {
setTimeout(()=>{ this.show = false },0)
}
使用click事件控制下拉框显示隐藏
如果选择器没有输入框,在使用 click 事件控制下拉框的显示隐藏时,需要添加一个方法,点击文档任意地方触发下拉框的隐藏事件
<template>
<div>
<button @click="handleClickDiv">111</button>
<ul v-if="show">
<li @click.stop="handleClickLi">111</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
show: !1
}
},
methods: {
handleClickDiv(){
this.show = !this.show
},
handleClickLi() {
console.log('handleClickLi')
}
}
}
</script>
解决方式
- 添加点击文档任意地方触发下拉框的隐藏事件(注意销毁组件时要解绑事件)
created() {
this.documentClickEvent = ()=> {
this.show = false
}
document.addEventListener('click',this.documentClickEvent)
},
destroyed() {
document.removeEventListener('click',this.documentClickEvent)
}
- 阻止选项的点击事件冒泡(避免两个点击事件冲突)
<template>
<div>
<button @click.stop="handleClickDiv">111</button>
<ul v-if="show">
<li @click.stop="handleClickLi">111</li>
</ul>
</div>
</template>
补充
上述方法,未考虑到多个组件时,绑定在document中的事件的影响,如果引入多次组件,会对组件间隐藏显示造成影响,需对document绑定的方法进行以下修改
this.documentClickEvent = (e) => {
if (
!this.$el.contains(e.target) ||
(!this.show && e.target == this.$refs.button)
) {
this.show = false;
} else {
this.show = true;
}
};
<button @click="handleClickDiv" ref="button">111</button>
解除 button 的冒泡,通过 ref 获取 Dom 对象,在所绑定的 document 点击事件中添加判断,不是当前组件中的 button 就隐藏,或者通过点击按钮隐藏了,就不再打开