@floating-ui/react介绍

半兽人 发表于: 2025-05-07   最后更新时间: 2025-05-07 11:15:22  
{{totalSubscript}} 订阅, 43 游览

@floating-ui/react 是一个专为 React 设计的库,用于创建浮动元素(如 tooltip、popover、dropdown 等)的位置定位和智能摆放。适配 React 的 API 和 Hook,如 useFloating()

它能解决的问题

浮动元素常见问题:

  • 不知道如何精准定位(相对于目标元素)
  • 避免被遮挡(视口边缘、滚动时不隐藏等)
  • 自动调整位置(比如空间不足时从下变上)

@floating-ui/react 会根据目标元素的位置、视口情况自动计算最优位置,并返回一系列用于定位的参数和 style。

安装

npm install @floating-ui/react

基本用法

下面是一个最简单的 tooltip 示例:

import React, { useState } from 'react';
import { useFloating, offset, flip, shift, autoUpdate } from '@floating-ui/react';

export default function Tooltip() {
  const [open, setOpen] = useState(false);

  const {
    x,
    y,
    reference,
    floating,
    strategy,
    update,
    refs,
  } = useFloating({
    placement: 'top',
    middleware: [offset(8), flip(), shift()],
    whileElementsMounted: autoUpdate,
  });

  return (
    <div>
      <button
        ref={reference}
        onMouseEnter={() => setOpen(true)}
        onMouseLeave={() => setOpen(false)}
      >
        Hover me
      </button>
      {open && (
        <div
          ref={floating}
          style={{
            position: strategy,
            top: y ?? 0,
            left: x ?? 0,
            backgroundColor: 'black',
            color: 'white',
            padding: '6px 12px',
            borderRadius: '4px',
            zIndex: 9999,
          }}
        >
          Tooltip content
        </div>
      )}
    </div>
  );
}

可以,你只需要在浮动层(弹出框)中也监听 onMouseEnter / onMouseLeave,让它和按钮共享控制逻辑,就能避免移动过去时关闭。

修改为支持鼠标移到弹出层里不关闭

import React, { useState } from 'react';
import { useFloating, offset, flip, shift, autoUpdate } from '@floating-ui/react';

export default function Tooltip() {
  const [open, setOpen] = useState(false);
  const [isHovering, setIsHovering] = useState(false);

  const {
    x,
    y,
    reference,
    floating,
    strategy,
  } = useFloating({
    placement: 'top',
    middleware: [offset(8), flip(), shift()],
    whileElementsMounted: autoUpdate,
  });

  const handleMouseEnter = () => {
    setOpen(true);
    setIsHovering(true);
  };

  const handleMouseLeave = () => {
    setIsHovering(false);
    // 延迟关闭,避免快速移动时闪烁
    setTimeout(() => {
      if (!isHovering) setOpen(false);
    }, 100);
  };

  return (
    <div>
      <button
        ref={reference}
        onMouseEnter={handleMouseEnter}
        onMouseLeave={handleMouseLeave}
      >
        Hover me
      </button>
      {open && (
        <div
          ref={floating}
          style={{
            position: strategy,
            top: y ?? 0,
            left: x ?? 0,
            backgroundColor: 'black',
            color: 'white',
            padding: '6px 12px',
            borderRadius: '4px',
            zIndex: 9999,
          }}
          onMouseEnter={handleMouseEnter}
          onMouseLeave={handleMouseLeave}
        >
          Tooltip content
        </div>
      )}
    </div>
  );
}

效果说明

  • 鼠标进入 button 或弹出框时,setOpen(true)
  • 鼠标移出时,会延迟一点时间判断是否还在浮动层,如果不在才 setOpen(false)
  • 这样可以避免用户快速从按钮移入弹出层时被误关闭

常用 Middleware

  • offset(px):浮动元素距离参考元素的偏移量。
  • flip():如果原来的位置空间不够,则自动翻转方向。
  • shift():防止浮动元素溢出视口。

高级功能(可选)

  • autoUpdate():自动监听滚动或窗口大小变化并重新计算位置。
  • 支持虚拟元素(如 chart 中的 tooltip)。
  • 与 Floating UI 核心库高度兼容,可按需自定义。
更新于 2025-05-07
在线,26分钟前登录

查看React更多相关的文章或提一个关于React的问题,也可以与我们一起分享文章