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
相关产品推荐
相关产品推荐

