跳到主要内容

useClickOutside

检测点击元素外部的 Hook,常用于实现下拉菜单、模态框等组件的点击外部关闭功能。

基本用法

点击外部区域触发回调:

实时编辑器
function Demo() {
  const [opened, setOpened] = useState(false);
  const ref = useClickOutside(() => setOpened(false));

  return (
    <div>
      <Button onClick={() => setOpened(true)}>打开下拉菜单</Button>
      {opened && (
        <div
          ref={ref}
          style={{
            marginTop: '10px',
            padding: '20px',
            backgroundColor: 'var(--ifm-color-emphasis-100)',
            borderRadius: '8px',
            border: '1px solid var(--ifm-color-emphasis-300)',
          }}
        >
          <div>点击外部关闭</div>
          <Button onClick={() => setOpened(false)} style={{ marginTop: '10px' }}>
            关闭
          </Button>
        </div>
      )}
    </div>
  );
}
结果
Loading...

自定义事件

可以自定义触发事件类型:

实时编辑器
function Demo() {
  const [opened, setOpened] = useState(false);
  const ref = useClickOutside(() => setOpened(false), ['mouseup', 'touchend']);

  return (
    <div>
      <Button onClick={() => setOpened(true)}>打开(自定义事件)</Button>
      {opened && (
        <div
          ref={ref}
          style={{
            marginTop: '10px',
            padding: '20px',
            backgroundColor: 'var(--ifm-color-emphasis-100)',
            borderRadius: '8px',
          }}
        >
          使用 mouseup 和 touchend 事件
        </div>
      )}
    </div>
  );
}
结果
Loading...

多个元素

监听多个元素的外部点击:

实时编辑器
function Demo() {
  const [opened, setOpened] = useState(false);
  const buttonRef = useRef();
  const dropdownRef = useRef();

  useClickOutside(() => setOpened(false), null, [buttonRef.current, dropdownRef.current]);

  return (
    <div>
      <Button ref={buttonRef} onClick={() => setOpened(!opened)}>
        切换
      </Button>
      {opened && (
        <div
          ref={dropdownRef}
          style={{
            marginTop: '10px',
            padding: '20px',
            backgroundColor: 'var(--ifm-color-emphasis-100)',
            borderRadius: '8px',
          }}
        >
          点击按钮或此区域外部关闭
        </div>
      )}
    </div>
  );
}
结果
Loading...

API

参数

function useClickOutside<T extends HTMLElement = any>(
handler: () => void,
events?: string[] | null,
nodes?: HTMLElement[]
): RefObject<T>
参数说明类型默认值
handler点击外部时触发的回调函数() => void-
events监听的事件类型数组string[] | null['mousedown', 'touchstart']
nodes要监听的多个元素节点数组HTMLElement[]-

返回值

返回一个 ref 对象,需要绑定到要监听的元素上。

RefObject<T>

使用场景

  • 下拉菜单: 点击菜单外部关闭
  • 模态框: 点击遮罩层关闭弹窗
  • 弹出面板: 点击外部收起面板
  • 表单: 点击外部保存草稿或取消编辑