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

React中onMouseOver/onMouseEnter事件中断滚动到指定区域问题求助

问题:页面滚动时悬停导航项会中断滚动

我做了一个图标导航栏,图标链接到页面不同区域,用state跟踪图标悬停状态来弹出提示框,这两个功能本身都正常,但页面滚动到某个区域后,悬停任意导航项会立即终止滚动。

复现行为

  • 点击FAQ,滚动正常
  • 点击Process,滚动正常
  • 再次点击FAQ后,悬停其他导航项,滚动直接中断

相关代码(已移除样式)

<ul>
  {navbarItems.map((Item, i) => (
    <Link key={i} href={Item.link}>
      <motion.li
      onMouseOver={() => setIsHovering(i)}
      onMouseLeave={() => setIsHovering(false)}
      >
        <Item.component />
        {isHovering === i && (
          <motion.div>
            <motion.div>
              <h4>{Item.name}</h4>
            </motion.div>
          </motion.div>
        )}
      </motion.li>
    </Link>
  ))}
</ul>

可能原因

这个问题大概率是父组件单一state更新触发整个导航栏重渲染,或是Link组件(比如Next.js的Link)在悬停时意外触发了锚点跳转的预加载/焦点逻辑,导致浏览器中断滚动行为。


解决方案

方案1:拆分组件,让每个导航项独立管理悬停状态

把导航项拆成独立组件,每个项自己维护悬停状态,这样悬停时只会重渲染当前项,不会影响整个导航栏和页面滚动:

// 独立导航项组件
const NavItem = ({ Item }) => {
  const [isHovering, setIsHovering] = useState(false);

  return (
    <Link href={Item.link}>
      <motion.li
        onMouseOver={() => setIsHovering(true)}
        onMouseLeave={() => setIsHovering(false)}
      >
        <Item.component />
        {isHovering && (
          <motion.div>
            <motion.div>
              <h4>{Item.name}</h4>
            </motion.div>
          </motion.div>
        )}
      </motion.li>
    </Link>
  );
};

// 父组件中使用
<ul>
  {navbarItems.map((Item, i) => (
    <NavItem key={i} Item={Item} />
  ))}
</ul>

方案2:阻止鼠标事件冒泡,避免触发Link的默认逻辑

在motion.li的鼠标事件中阻止冒泡,避免Link组件捕获到事件后执行干扰滚动的逻辑:

<motion.li
  onMouseOver={(e) => {
    e.stopPropagation();
    setIsHovering(i);
  }}
  onMouseLeave={(e) => {
    e.stopPropagation();
    setIsHovering(false);
  }}
>
  {/* 图标和提示框内容 */}
</motion.li>

方案3:缩小Link的包裹范围

只让Link包裹图标部分,不要包含悬停提示框,这样提示框的显示不会关联到Link的锚点行为:

<li>
  <Link href={Item.link}>
    <motion.div
      onMouseOver={() => setIsHovering(i)}
      onMouseLeave={() => setIsHovering(false)}
    >
      <Item.component />
    </motion.div>
  </Link>
  {isHovering === i && (
    <motion.div>
      <motion.div>
        <h4>{Item.name}</h4>
      </motion.div>
    </motion.div>
  )}
</li>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 13:45:31