页面中有两个select选择框,无论哪个select框处于打开状态,点击除本身之外的任意地方,该select框关闭。
思路
首先点击document任意位置隐藏该元素,然后给该元素绑定click事件,阻止冒泡到该元素,则可以顺利实现需求。
注意:判断点击事件发生在区域外的条件是:
- 点击事件的对象不是目标区域本身
- 事件对象同时也不是目标区域的子元素

page.js
import React from 'react';
import { Icon, Checkbox } from 'antd';
import $state from './state';
import { observer } from 'mobx-react'
const CheckboxGroup = Checkbox.Group
const plainOptions = ['Jack', 'Yumi', 'Jim'];
const plainOptions1 = ['一班', '二班', '三班'];
@observer
class ColseWrap extends React.Component {
constructor(props) {
super(props)
this.state = {}
}
componentDidMount() {
$state.closeLandBox(document, '.select-box', $state)
$state.closDealBox(document, '.deal-status', $state)
}
handleChange = (value, type = 'select') => {
if (type === 'deal') {
$state.checkedList1 = value
} else {
$state.checkedList = value
}
}
changeIcon = (e, type = 'select') => {
if (type === 'deal') {
$state.isDealFlag = !$state.isDealFlag
} else {
$state.isShow = !$state.isShow
}
}
render() {
console.log($state.isShow, '-------');
return (
<div id='close_box'>
<div className='select-box'>
<div className='select-top'>
<span>优秀团员</span>
<i onClick={this.changeIcon} className={$state.isShow ? "caret-up" : 'caret-down'} />
</div>
{
$state.isShow ? <div className='select-content'>
<CheckboxGroup
options={plainOptions}
value={$state.checkedList}
onChange={this.handleChange}
/>
</div> : ''
}
</div >
<div className='deal-status'>
<div className='deal-top'>
<span>优秀班级</span>
<i onClick={(e) => { this.changeIcon(e, 'deal') }} className={$state.isDealFlag ? "caret-up" : 'caret-down'} />
</div>
{
$state.isDealFlag ?
<div className='deal-content'>
<CheckboxGroup
options={plainOptions1}
value={$state.checkedList1}
onChange={(e) => { this.handleChange(e, 'deal') }}
/>
</div> : ''
}
</div >
</div>
)
}
}
export default ColseWrap
state.js
import { observable, action, toJS } from "mobx";
import $ from 'jquery'
class State {
@observable isShow = false
@observable isDealFlag = false
@observable checkedList = ['Jack', 'Yumi']
@observable checkedList1 = ['一班']
@action closeLandBox = (class1, class2,$state) => {
$(class1).mouseup(function (e) {
e.stopPropagation()
var _con = $(class2);
if (!_con.is(e.target) && _con.has(e.target).length === 0) {
$state.isShow = false
}
else {
if (e.target.className == 'caret-down') {
$state.isShow = false
} else {
$state.isShow = true
}
}
})
}
@action closDealBox = (class1, class2,$state) => {
$(class1).mouseup(function (e) {
e.stopPropagation()
var _con = $(class2);
if (!_con.is(e.target) && _con.has(e.target).length === 0) {
$state.isDealFlag = false
}
else {
if (e.target.className == 'caret-down') {
$state.isDealFlag = false
} else {
$state.isDealFlag = true
}
}
})
}
}
export default new State()
index.less样式文件
#close_box {
i.caret-up {
transition: transform 0.3s ease;
background: url('./icon_select_arrow_blue.png') center no-repeat;
background-size: contain;
width: 14px;
height: 14px;
display: inline-block;
transform: translateY(-50%) rotate(180deg) !important;
cursor: pointer;
}
i.caret-down {
transition: transform 0.3s ease;
background: url('./icon_select_arrow_blue.png') center no-repeat;
background-size: contain;
width: 14px;
height: 14px;
display: inline-block;
cursor: pointer;
}
//选择框
.select-box {
position: absolute;
z-index: 3;
top: 20px;
width: 110px;
.select-top {
background: #112331;
height: 30px;
line-height: 28px;
padding-left: 10px;
font-weight: 700;
border: 1px solid #3bf;
border-radius: 3px;
color: #3bf;
position: relative;
i {
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 10px;
}
}
.select-content {
border: 1px solid #3bf;
border-top: 0;
background: #112331;
padding: 10px;
.ant-checkbox-wrapper {
display: block;
margin: 0px 0px 5px 0px;
span {
color: #3bf;
}
}
}
}
.deal-status {
position: absolute;
z-index: 5;
top: 20px;
left: 150px;
width: 145px;
.deal-top {
background: #112331;
height: 30px;
line-height: 28px;
padding-left: 10px;
font-weight: 700;
border: 1px solid #3bf;
border-radius: 3px;
color: #3bf;
position: relative;
i {
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 10px;
}
}
.deal-content {
border: 1px solid #3bf;
border-top: 0;
background: #112331;
padding: 10px;
.ant-checkbox-wrapper {
display: block;
margin: 0px 0px 5px 0px;
span {
color: #3bf;
}
}
}
}
}