前言:下文中提到的下拉框、对话框以及其他UI组件都是antd UI库中的,更多操作请看antd官方文档API,点击此处跳转至antd的下拉菜单dropdown组件官网。
情景/目标:工作中遇到的需求:
1、当下拉菜单展开多层时(如下图 有二级下拉菜单展开),点击页面其他地方,只是收起二级菜单,一级菜单不收起,再次点击收起一级菜单。antd默认点击别处,展开的菜单全部收起
2、当页面中有下拉菜单展开时,点击空白处任何地方,都是收起一层下拉菜单,页面中下拉菜单全部收起后,点击、双击等操作才会出发页面中的其他点击事件。
问题1的解决方法:Dropdown组件的 visible 和 onVisibleChange属性
visible属性控制Dropdown组件的显示与隐藏,true为显示,false为隐藏
onVisibleChange在visible被改变时调用
所以,当两个属性都不写的时候,就是系统的、点击页面空白处切换显示与隐藏
当指定visible属性,就根据visible的值来控制显隐,此时点击空白处不再能切换显隐,除非再指定onVisibleChange属性来配合
两个属性一起使用,既可以通过visible控制显隐,又可以通过点击页面空白来控制显隐。
变量:visible}//点击空白处时正常显隐,因为把变量改变了,显隐也就改变了
/>
到这里,我们知道了怎么单独控制菜单的显隐。所以我们可以在state里指定一个first变量来控制一级菜单的显隐,就可以让一级菜单的visible={first} 同理,令二级菜单的visible={second}
于是,在二级菜单里面可以设置visible和onVisibleChange:
visible={this.state.second}
//点击页面其他地方时:
onVisibleChange={visible=>
this.setState({
first:true,//保持一级依然显示
second:visible//二级菜单显示与隐藏
})
}
这样二级菜单关闭时,就不会自动把一级菜单也关闭了。
然后控制一级菜单,在一级菜单里面设置visible和onVisibleChange:
visible={this.state.first}
onVisibleChange={this.handleFirstChange}//这一步操作不止一步,所以另写一个函数handleFirstChange来实现,方便阅读
//点击空白处时
handleFirstChange=(visible)=>{
if(this.state.second){//判断,如果二级菜单依然在展开,就保持一级为true
this.setState({
first:true
})
}else{
this.setState({
first:visible//否则,二级菜单已经关闭了,一级菜单正常关闭
})
}
}
问题二:菜单弹出时,阻止页面其他点击动作,无论怎么点击,都只是收起一层菜单,直至菜单全部收起
解决方法:添加蒙版阻止其他事件。这里采用加了一个Modal组件。
使mask层不显示、对话框也不显示:
Modal与Dropdown是兄弟关系即可
你可能已经注意到了Modal也有visible 与Dropdown相同,也是用来控制显隐。
个人工作整理,欢迎提建议! 完结撒花
彩蛋:如果有些地方只能放一个子元素,但是我们想要放多个,必须在外层包一个div吗???-------------不必!用一对<> >空标签包裹即可。