React Hook:检查外部点击

2023-11-29 21:50:52 浏览数 (1)

当我们在 React 中实现下拉菜单或抽屉组件时,这些组件通常需要在单击菜单按钮或组件外部时关闭。

为了在我们的自定义组件中允许这种行为,我们可以创建一个自定义钩子,每当需要时,它可以应用相同的行为。

这里是一个简单的自定义钩子,它检查鼠标单击是否在当前组件的外部。

代码语言:javascript复制
const useCheckOutside = 
(clickOutside: () => void, exceptId?: string) => ...

我们将这个钩子命名为 useCheckOutside,它接收 clickOutside 函数作为一个属性,允许父组件接收事件。

exceptId 是一个可选属性,可用于在点击处不希望关闭行为时忽略它。我们需要这个属性,因为通常菜单或下拉按钮也是外部点击的一部分,按钮的 onClick 事件将使菜单或下拉框的可见性变为可见,而外部点击将可见性变为隐藏。下面的函数描述了 exceptId 将在 mousedown 事件中被忽略。

代码语言:javascript复制
const checkOutsideClick = (event: any) => {
      if (
        ref.current &&
        !ref.current.contains(event.target) &&
        event.target.id !== exceptId
      ) {
        clickOutside();
      }
    };

document.addEventListener('mousedown', checkOutsideClick);

以下是 useCheckOutside 钩子的完整代码,以及如何使用的简单示例。

代码语言:javascript复制
import { useEffect, useRef } from 'react';

const useCheckOutside = 
      (clickOutside: () => void, 
       exceptId?: string) => {

  const ref = useRef<any>();

  useEffect(() => {
    const checkOutsideClick = (event: any) => {
      if (
        ref.current &&
        !ref.current.contains(event.target) &&
        event.target.id !== exceptId
      ) {
        clickOutside();
      }
    };
    document.addEventListener('mousedown', checkOutsideClick);
    return () => {
      document.removeEventListener('mousedown', checkOutsideClick);
    };
  }, [clickOutside]);

  return ref;
};

export default useCheckOutside;

const handleOutsideClick = () => {
     setOpen(false);
}

const ref = useCheckOutside(handleOutsideClick, "buttonId");

return <>
         <button id="buttonId" type="button" 
                 onClick={(e) => {
                   setOpen(true)
                 }
          >
          Menu
          </button>

          {open && <Menu ref={ref} />}
        </>

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

0 人点赞