一个简单的效果,点击导航栏弹出菜单后,在菜单外点击触发失焦,自动关闭菜单
本文采用Vant组件
核心:通过触发菜单内的input
聚焦失焦控制显示/隐藏
导航栏:
<van-nav-bar title="导航栏" left-arrow @click="handleRight">
<van-icon name="ellipsis" v-slot:right />
</van-nav-bar>
菜单:
<div v-show="isShowMenu" class="nav-menu">
<ul>
<li v-for="item in menuList"
:key="item"
@click="handleMenu(item)">{{ item }}</li>
</ul>
<input ref="MenuInput" type="text" @blur="menuBlur" />
</div>
.nav-menu{
position: fixed;
top: 40px;
right: 5px;
input{
position: absolute;
left: 0;
bottom: 0;
width: 0;
height: 0;
margin: 0;
border: none;
outline: 0;
opacity: 0;
-webkit-appearence: none;
}
}
事件:
export default{
name: 'custom-nav',
data(){
return {
isShowMenu: false,// 控制菜单
menuList: ['操作1', '操作2'],// 菜单
}
},
methods: {
handleMenu(item){// 点击菜单项
console.log(item)
},
menuBlur(){// 输入框失焦 =》 隐藏菜单
this.isShowMenu = false
},
handleRight(){// 点击导航栏右侧
this.isShowMenu = !this.isShowMenu
// trigger焦点
this.$nextTick(() => {
if(this.$refs.MenuInput){
this.$refs.MenuInput.focus()
}else{
this.$refs.MenuInput.blur()
}
})
}
}
}
问题:
菜单栏点击事件
handleMenu
与输入框失焦menuBlur
冲突由于js是单线程,所以两者无法同时进行,加个延迟
menuBlur(){ setTimeout(() => { this.isShowMenu = false; }, 100) }
输入框聚焦同时弹出键盘
如果把input类型设置为hidden反而不能聚焦,所以加个只读属性readonly
<input ref="MenuInput" readonly type="text" @blur="menuBlur" />
其他组件同时出发失焦事件
在用ElementUI的日期选择器时,其自带的@blur
会上浮,不知道算不算bug。
此处带上事件修饰符可解决<el-date-picker @blur.native.capture="pickerBlur"></el-date-picker>