You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React MUI Popper鼠标悬停激活后移至弹窗消失无法点击链接问题

解决MUI Popper鼠标移到弹窗时立即消失的问题

问题原因

触发元素和Popper是同级DOM元素,鼠标从触发元素移向Popper时,触发元素的mouseOut事件会先触发,此时Popper的mouseOver事件还未执行,导致弹窗被提前关闭。同时你当前的inBox状态存在时序问题:触发元素的mouseOut执行时,Popper的mouseOver还没触发,inBox仍为false,无法阻止弹窗关闭。

解决方案

通过延迟关闭+状态联动处理,核心逻辑是:鼠标离开触发元素时不立即关闭弹窗,等待一小段时间,若这段时间内鼠标进入Popper则取消关闭;若未进入再执行关闭。同时统一管理弹窗状态,确保鼠标在触发元素或Popper上时弹窗保持打开。

修改后的代码示例

import "./styles.css";
import React, { useState, useRef } from "react";
import { Box, Popper } from "@mui/material";

export default function App() {
  const [anchorEl, setAnchorEl] = useState<(EventTarget & Element) | null>(null);
  const closeTimerRef = useRef<NodeJS.Timeout | null>(null);

  // 打开弹窗,清除之前的关闭定时器
  const handleOpen = (e: React.MouseEvent) => {
    if (closeTimerRef.current) {
      clearTimeout(closeTimerRef.current);
    }
    setAnchorEl(e.currentTarget);
  };

  // 触发延迟关闭弹窗的操作
  const handleTriggerLeave = () => {
    closeTimerRef.current = setTimeout(() => {
      setAnchorEl(null);
    }, 200); // 200ms延迟,可根据需求调整
  };

  // 鼠标进入弹窗时,取消关闭操作
  const handlePopperEnter = () => {
    if (closeTimerRef.current) {
      clearTimeout(closeTimerRef.current);
    }
  };

  // 鼠标离开弹窗时,直接关闭弹窗
  const handlePopperLeave = () => {
    setAnchorEl(null);
  };

  const open = !!anchorEl;

  return (
    <Box>
      <Box
        component="div"
        sx={{
          backgroundColor: "red",
          width: "100px",
          height: "100px"
        }}
        onMouseEnter={handleOpen}
        onMouseLeave={handleTriggerLeave}
      />
      {open && (
        <Popper open={open} anchorEl={anchorEl} placement="bottom-start">
          <Box
            sx={{
              backgroundColor: "green",
              width: "170px",
              height: "70px",
              padding: "10px"
            }}
            onMouseEnter={handlePopperEnter}
            onMouseLeave={handlePopperLeave}
          >
            {/* 可添加需要点击的链接 */}
            <a href="#link1">链接1</a>
            <a href="#link2" style={{ marginLeft: "10px" }}>链接2</a>
          </Box>
        </Popper>
      )}
      <Box
        onMouseEnter={handleOpen}
        onMouseLeave={handleTriggerLeave}
        sx={{
          backgroundColor: "blue",
          width: "100px",
          height: "100px"
        }}
      />
    </Box>
  );
}

代码说明

  • 用useRef保存关闭定时器的引用,确保能在需要时清除定时器,避免重复触发关闭。
  • 替换onMouseOver/onMouseOut为onMouseEnter/onMouseLeave,这类事件只会在鼠标进入/离开整个元素时触发,不会因为子元素频繁触发,更适合处理整体hover状态。
  • Popper内的onMouseEnter清除关闭定时器,确保弹窗保持打开;onMouseLeave直接关闭弹窗,符合正常交互逻辑。

内容的提问来源于stack exchange,提问作者GRZa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 05:34:58