React 与 JS 事件处理程序用于在组件外部单击,哪一个是最佳实践?

问题描述 投票:0回答:1

我正在 React 中创建一个菜单组件,当菜单打开并且用户单击菜单外的任何位置时,它将关闭菜单组件。我看到有两种方法,一种是像这样使用JS事件监听器

import React, { useState, useEffect } from 'react';

const Dropdown = () => {
  const [isOpen, setIsOpen] = useState(false);
  
  const toggleDropdown = () => setIsOpen(!isOpen);

  useEffect(() => {
    const handleClickOutside = (event) => {
      if (isOpen && !event.target.closest('.dropdown')) {
        setIsOpen(false);
      }
    };

    document.addEventListener('mousedown', handleClickOutside);
    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
    };
  }, [isOpen]);

  return (
    <div className="dropdown" onClick={toggleDropdown}>
      {isOpen ? (
        <div className="dropdown-menu">
          {/* Dropdown Content */}
        </div>
      ) : null}
    </div>
  );
};

另一种方法是使用 React 事件处理程序,如下所示:

import React, { useState } from 'react';

const Dropdown = () => {
  const [isOpen, setIsOpen] = useState(false);

  // Toggle Dropdown open/close
  const toggleDropdown = () => setIsOpen(!isOpen);

  // Close Dropdown if open, when clicking outside
  const handleClickOutside = (e) => {
    if (isOpen && !e.currentTarget.contains(e.target)) {
      setIsOpen(false);
    }
  };

  return (
    <div onClick={handleClickOutside}>
      <button onClick={(e) => {
        e.stopPropagation(); // Prevents click from "bubbling" up to the div
        toggleDropdown();
      }}>
        Toggle Dropdown
      </button>
      {isOpen && (
        <div className="dropdown-menu">
          {/* Dropdown content */}
        </div>
      )}
    </div>
  );
};

那么哪一种更适合最佳实践呢?一方面你必须分配全局事件监听器,一方面你要处理反应中的事件冒泡。

javascript reactjs event-handling javascript-events
1个回答
0
投票

好吧,惯用的方式是 React 中的任何东西都是 React。所以是的,坚持合成事件。请记住,这仅适用于“反应性”行为。

暂时将其放在一边,重点关注事件 API。因此,一旦您单击某个按钮,该按钮就会获得焦点。一旦您单击其他内容,该按钮就会失去焦点并触发模糊事件。现在,我们可以利用它,而不是监听通用的点击事件,因此:

import React, {useState} from 'react';

export function Foo(props) {
  const [isOpen, setIsOpen] = useState(false)

  const handleBlur = (e) => {
    setIsOpen(false)
  }

  const handlePointer = (e) => {
    setIsOpen(!isOpen)
  }

  return (
    <div>
      <button onPointerDown={handlePointer} onBlur={handleBlur}>Click me</button>
      {isOpen ? <div>I'm showing!</div> : null}
    </div>
  );
}

不要介意我注册 onPointerDown 而不是 onClick。这是一种习惯的力量。 这是MDN

© www.soinside.com 2019 - 2024. All rights reserved.