前言:下文中提到的下拉框、对话框以及其他UI组件都是antd UI库中的,更多操作请看antd官方文档API,点击此处跳转至antd的下拉菜单dropdown组件官网。
情景/目标:工作中遇到的需求:
1、当下拉菜单展开多层时(如下图 有二级下拉菜单展开),点击页面其他地方,只是收起二级菜单,一级菜单不收起,再次点击收起一级菜单。antd默认点击别处,展开的菜单全部收起

2、当页面中有下拉菜单展开时,点击空白处任何地方,都是收起一层下拉菜单,页面中下拉菜单全部收起后,点击、双击等操作才会出发页面中的其他点击事件。
问题1的解决方法:Dropdown组件的 visible 和 onVisibleChange属性
visible属性控制Dropdown组件的显示与隐藏,true为显示,false为隐藏
onVisibleChange在visible被改变时调用

所以,当两个属性都不写的时候,就是系统的、点击页面空白处切换显示与隐藏
当指定visible属性,就根据visible的值来控制显隐,此时点击空白处不再能切换显隐,除非再指定onVisibleChange属性来配合
两个属性一起使用,既可以通过visible,又可以通过点击页面空白来控制显隐。
1 2 3 4 | <Dropdown visibel={变量}//通过该变量来手动控制显隐 onVisibleChange={visible=>变量:visible}//点击空白处时正常显隐,因为把变量改变了,显隐也就改变了 /> |
到这里,我们知道了怎么单独控制菜单的显隐。所以我们可以在state里指定一个first变量来控制一级菜单的显隐,就可以让一级菜单的visible={first} 同理,令二级菜单的visible={second}
于是,在二级菜单里面可以设置visible和onVisibleChange:
1 2 3 4 5 6 7 8 | visible={this.state.second} //点击页面其他地方时: onVisibleChange={visible=> this.setState({ first:true,//保持一级依然显示 second:visible//二级菜单显示与隐藏 }) } |
这样二级菜单关闭时,就不会自动把一级菜单也关闭了。
然后控制一级菜单,在一级菜单里面设置visible和onVisibleChange:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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层不显示、对话框也不显示:
1 2 3 4 5 6 | <Modal visible={this.state.first || this.state.second}//一级菜单、二级菜单,只要有一个是显示的,蒙层就显示 style={<!-- -->{ display: "none" }} mask={false} > </Modal> |
Modal与Dropdown是兄弟关系即可
你可能已经注意到了Modal也有visible 与Dropdown相同,也是用来控制显隐。
个人工作整理,欢迎提建议! 完结撒花??
彩蛋:如果有些地方只能放一个子元素,但是我们想要放多个,必须在外层包一个div吗???-------------不必!用一对<>>空标签包裹即可。