React Javascript onclick вне div

#javascript #html #reactjs #onclick #hide

#javascript #HTML #reactjs #onclick #скрыть

Вопрос:

выход из системы со значком svg

Я работаю над веб-сайтом, и в настоящее время у меня есть значок svg для выхода из системы. при нажатии на значок появляется наложение с опцией выхода. когда пользователь нажимает на выход, он должен выполнять определенную операцию, а когда пользователь нажимает вне div, наложение должно быть скрыто. мне не удается достичь этого.

я попытался сфокусироваться на div с помощью tabIndex, но тогда опция выхода из системы больше не доступна.

Header.js

  import React, { Component } from "react";
    import ReactDOM from "react-dom";
    class MainHeader extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          logOutShown: false
        };
      }
    render() {
    var guiResult = [];
    if (this.state.logOutShown) {
      guiResult.push(
        <div className="Login__Overlay__Frame">
          <div className="User__Login__Overlay">
          <div className="Login__Content" tabIndex="1" onFocus={this.alerting.bind(this)} onBlur={this.toggleOverlay.bind(this)}>Signout</div>
          </div>
        </div>
      );
    }

    return (
            <div className="Header__Icon">
              <div className="Icons__Log__In" tabIndex="0" onClick={this.validate.bind(this)} onBlur={this.toggleOverlay.bind(this)}/>
              {guiResult}
            </div>
    );
  }

  toggleOverlay(){
    console.log("toggle overlay");
    this.setState({ logOutShown: false});
  }

  validate() {
    console.log("validate:");
    this.setState(
      {
        logOutShown: true
      }
    );
  }
  

Комментарии:

1. Вы можете добавить обработчики для наложения <div className="User__Login__Overlay" onClick={this.toggleOverlay.bind(this)}>

2. Вы можете проверить щелчок при наложении, но есть проблема !!. Когда вы нажимаете на что-либо внутри наложения, это тоже отображается. Что я обычно делаю, так это создаю компонент для выполнения наложения, а внутри наложения находится контейнер, и этот контейнер подключается к onClick и вызывает event.stopPropagation() . Затем это остановит нажатие на ваш контент, вызывающее событие на оверлее.

3. @Keith сейчас я попробую, создав новый компонент для наложения. может быть, вы можете предоставить мне общую структуру нового компонента, которая будет выглядеть так, как я запутался в этом «и внутри наложения есть контейнер, и этот контейнер подключается к onClick и вызывает event.stopPropagation()»

4. @Kirill как упоминал Кит, это не сработало.

5. Я посмотрю, смогу ли я создать быстрый фрагмент. дайте нам 10..

Ответ №1:

Вы можете использовать хорошо написанную библиотеку, подобную этой: react-outside-click-handler

пример:

 import OutsideClickHandler from 'react-outside-click-handler';

function MyComponent() {
  return (
    <OutsideClickHandler
      onOutsideClick={() => {
        alert('You clicked outside of this component!!!');
      }}
    >
      Hello World
    </OutsideClickHandler>
  );
}
  

Редактировать:

Сегодня, когда я редактирую этот комментарий, множество новых библиотек привносят эту функцию в ваш код.

Если вы используете библиотеку компонентов, проверьте, существует ли в ней утилита. (чакра, мантия, материал-пользовательский интерфейс).

Другое решение существует внутри библиотек hooks, таких как react-use.

Ответ №2:

Вот простой пример, я использую перехватчики реакции здесь вместо классов, но вы тоже можете использовать классы..

Основная часть — это onClick в контейнере div, если вы запустите приведенный ниже пример и нажмете на диалоговое окно, оно не закроется, но нажатие на наложение закроет.

e.stopPropagation() В div контейнера — это то, что останавливает события содержимого, запускающие события на оверлее. Вместо использования stopPropagation другим вариантом является проверка target amp; currentTarget внутри onClick наложения..

 const {useState} = React;


function Overlay(props) {
  const {contents} = props;
  const [open, setOpen] = useState(true);
  if (open) {
    return <div className="overlay" onClick={() => setOpen(false)}>
      <div onClick={(e) => {
        //stop clicks getting to the overlay
        e.stopPropagation();
      }}className="overlay-container">
        {contents()}
      </div>
    </div>
  }
  return null;
}


ReactDOM.render(<React.Fragment>
  This is some content to overlay.<br/>
  for testing..
  <Overlay contents={() =>
    <div>This is the contents, clicking here wont effect ovelay</div>
  }/>
</React.Fragment>, document.querySelector('#mount'));  
 .overlay {
  position: fixed;
  background-color: rgba(100,100,100,0.5);
  left: 0;
  top: 0;
  bottom: 0;
  right: 0;
}

.overlay-container {
  border: 1px solid black;
  background-color: white;
  position: absolute;
  top: 30px;
  left: 30px;
  width: 200px;
  height: 80px;
  padding: 5px;
}  
 <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="mount"></div>  

Ответ №3:

Используйте ссылки react https://reactjs.org/docs/refs-and-the-dom.html#creating-refs

Вы проверяете наличие target события и используете это для show/hide кнопки выхода.

добавьте прослушиватель событий при монтировании компонента.

 componentWillMount() { document.addEventListener("click", this.handleClickOutside, false); }
  

удалите прослушиватель событий, когда компонент смонтирован.

 componentWillUnmount() { document.removeEventListener("click", this.handleClickOutside, false); }
  

выполните проверку внешнего щелчка примерно так

 handleClickOutside(e) {
    if(this.submitPopoverRef.contains(e.target)) {
        // the click happened in the component
        // code to handle the submit button
        // submit();
        return;
    } 

    // click happened outside the component
    // hide the popover
    this.handleClick(); // set the state false
}

<div ref={node => this.submitPopoverRef = node}> 
... Your code here...

</div>
  

Ответ №4:

Основываясь на ответе @keith: использование перехватчиков реакции, а также классов: предполагается, что родительский и дочерний разделы, где вы хотели бы, чтобы родительский div обрабатывал щелчок ТОЛЬКО тогда, когда щелчок не был внутри дочернего div:

 const clickedParent = () => {};
const clickedChild = () => {};  

 <div onClick={clickedParent}>
  <div className="selc-hd-so-remove" onClick={e=> { e.stopPropagation(); clickedChild(); }} > Child Div Clicked</div>
</div>
Parent Div Clicked
</div>  

Ответ №5:

Необходимо использовать stopPropagation для дочерних элементов

 export default function App() {
  const parentHandler = () => {
    console.log("Parent");
  };
  const childHandler = (e) => {
    e.stopPropagation();
    console.log("Child");
  };

  return (
    <div className="App">
      <div onClick={parentHandler}>
        <div onClick={childHandler}>Child Div</div>
        Parent Div
      </div>
    </div>
  );
}