Обнаружение кликов за пределами div и меню переключения - PullRequest
2 голосов
/ 21 октября 2019

У меня есть меню переключения, и я пытаюсь обнаружить события щелчка за пределами меню, чтобы иметь возможность закрыть меню. Я могу закрыть меню, когда пользователь щелкает за пределами меню, однако, чтобы открыть меню снова, вы бынужно дважды щелкнуть по нему, кто-нибудь знает, что я должен сделать, чтобы это исправить, (меню должно открываться одним щелчком мыши)

const RightMenu = ({ t, history }) => {
  let [menuOpen, setMenuOpen] = useState(false);

  const menuDiv = useRef({});
  const toggleMenu = useRef();

  useEffect(() => {
    window.addEventListener("click", () => {
      if ((menuDiv.current.style.display = "block")) {
        menuDiv.current.style.display = "none";
      }
    });
    return () => {
      window.removeEventListener("click", () => {});
    };
  }, []);

  const handleClick = e => {
    e.stopPropagation();
    if (menuOpen === false) {
      menuDiv.current.style.display = "block";
      setMenuOpen(true);
    }
    if (menuOpen === true) {
      menuDiv.current.style.display = "none";
      setMenuOpen(false);
    }
  };

  return (
    <div>
      <div
        id="menu"
        ref={menuDiv}
        style={{
          display: "none"
        }}
      >Menu items</div>

      <div
        className="text-center"
        ref={toggleMenu}
        onClick={e => handleClick(e)}
      > Menu Button</div> 
    ) 
}

Ответы [ 4 ]

0 голосов
/ 21 октября 2019
const RightMenu = ({ t, history }) => {
let [menuOpen, setMenuOpen] = useState(false);


 useEffect(() => {
 window.addEventListener("click", () => {
 setMenuOpen(prevState => {
  return !prevState
 })
  });
return () => {
  window.removeEventListener("click", () => {});
};
}, []);

const handleClick = () => {
 e.stopPropagation();
 setMenuOpen(!menuOpen);
};

return (
<div>
  {menuOpen && (<div
    id="menu"

  >Menu items</div>)}

  <div
    className="text-center"

    onClick={handleClick}
  > Menu Button</div> 
) 

Для этого вам не нужны ссылки, вы можете условно отобразить меню на основе состояния menuOpen, как в приведенном примере.

0 голосов
/ 21 октября 2019
    @Watch('openDropdown')
        openHandler(newValue) {
            newValue ? this.setOpen() : this.setClose();
        }
        componentWillLoad() {
            document.addEventListener('click', this.handleClick, false)
        }
        componentDidUpdate() {

            //
            if (this.dropdownNode != null && this.collapsableIconNode != null) {
                this.dropdownNode.style.top = this.collapsableIconNode.offsetTop + 20 + 'px'
                this.dropdownNode.style.left = this.collapsableIconNode.offsetLeft - 11 + 'px'
            }

        }
        componentDidUnload() {
            document.removeEventListener('click', this.handleClick, true)
        }
        handleClick = (e) => {
            if (this.collapsableIconNode.contains(e.target)) {
                this.openDropdown = true;
            }
            else {
                this.handleClickOutside()
            }

        }
        handleClickOutside() {
            this.openDropdown = false;
        }



    <span ref={collapsableIconNode => this.collapsableIconNode = collapsableIconNode as HTMLSpanElement} id="collapseIcon" class="collapsable-icon" onClick={() => this.setOpen()}>

This is Written in StencilJS, Logic is same,It is similar to React!!
0 голосов
/ 21 октября 2019

Я недавно столкнулся с той же проблемой. Я закончил тем, что использовал эту библиотеку - https://github.com/Andarist/use-onclickoutside

Работал отлично для меня. Минимальное усилиеОн охватывает все крайние случаи.

Может быть, вам стоит попробовать.

0 голосов
/ 21 октября 2019

Вы фактически не удаляете прослушиватель событий из окна, когда ваш компонент отключается. Второй аргумент removeEventListener должен быть ссылкой на ту же функцию, которую вы добавили с помощью addRemoveListener. Например,

  useEffect(() => {
    const closeMenu = () => {
      if ((menuDiv.current.style.display = "block")) {
        menuDiv.current.style.display = "none";
      }
    };
    window.addEventListener("click", closeMenu);
    return () => {
      window.removeEventListener("click", closeMenu);
    };
  }, []);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...