学无先后,达者为师

网站首页 前端文档 正文

js+react解决点击除元素以外的任意地方隐藏元素

作者:小五Ivy 更新时间: 2022-02-20 前端文档

页面中有两个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)//如果不传$state,即使相关的数据发生改变,也不会触发render,具体原因还不是很清楚
  }


  //checkebox的选择
  handleChange = (value, type = 'select') => {

    if (type === 'deal') {
      $state.checkedList1 = value
    } else {
      $state.checkedList = value
    }
  }

  //点击icon,改变icon的状态
  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 = ['一班']
  
  //在body的任意位置点击一下,选择框合上
  @action closeLandBox = (class1, class2,$state) => {

    $(class1).mouseup(function (e) {
    
      e.stopPropagation()//阻止事件冒泡

      var _con = $(class2); // 设置目标区域

      //判断点击事件发生在区域外的条件是:1. 点击事件的对象不是目标区域本身 2. 事件对象同时也不是目标区域的子元素
      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) {
      // console.log(e.target, e.target.name);
      e.stopPropagation()
      var _con = $(class2); // 设置目标区域

      //判断点击事件发生在区域外的条件是:1. 点击事件的对象不是目标区域本身 2. 事件对象同时也不是目标区域的子元素
      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;
        }
      }
    }
  }
}

原文链接:https://blog.csdn.net/weixin_44471622/article/details/105642387

栏目分类
最近更新