使用MUI Menu添加HTML元素时布局出现异常滚动跳转问题
问题根源
关闭Menu时,MUI默认会将焦点恢复到触发它的按钮(restoreFocus默认值为true)。而你在Menu打开后给按钮上方添加了div,导致按钮的页面位置发生变化,浏览器会自动滚动到获得焦点的按钮,从而出现大幅跳转。
解决方案
1. 禁用Menu的焦点恢复行为
直接设置Menu的restoreFocus属性为false,阻止关闭时将焦点返回按钮,从根源避免浏览器自动滚动:
import { useState } from 'react'; import Menu from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; import Button from '@mui/material/Button'; export default function App() { const [anchorEl, setAnchorEl] = useState(null); const open = Boolean(anchorEl); const [hasDiv, setHasDiv] = useState(false); const handleClick = (event) => { setAnchorEl(event.currentTarget); }; const handleClose = () => { setAnchorEl(null); }; const addDiv = () => { setHasDiv(true); }; return ( <div> {hasDiv && <div style={{ height: '200px', backgroundColor: '#eee' }}>新增的div</div>} <Button id="basic-button" aria-controls={open ? 'basic-menu' : undefined} aria-haspopup="true" aria-expanded={open ? 'true' : undefined} onClick={handleClick} style={{ marginTop: '500px' }} > 打开菜单 </Button> <Menu id="basic-menu" anchorEl={anchorEl} open={open} onClose={handleClose} restoreFocus={false} // 关键:禁用焦点恢复 > <MenuItem onClick={addDiv}>添加上方div</MenuItem> <MenuItem onClick={handleClose}>关闭</MenuItem> </Menu> </div> ); }
2. 若需保留焦点恢复,手动控制滚动位置
如果你需要关闭Menu后焦点回到按钮,可在关闭时记录当前滚动位置,恢复焦点后强制保持原位置:
const handleClose = () => { // 记录关闭前的滚动位置 const scrollPos = window.pageYOffset || document.documentElement.scrollTop; setAnchorEl(null); // 下一帧恢复滚动位置,覆盖浏览器自动滚动行为 requestAnimationFrame(() => { window.scrollTo(0, scrollPos); }); };
3. 禁用Menu打开时的自动滚动(可选)
如果连Menu打开时的自动滚动都不需要,可通过PopperProps修改Popper的行为,关闭自动滚动到锚点的逻辑:
<Menu // 其他属性 PopperProps={{ modifiers: [ { name: 'preventOverflow', options: { enabled: false, // 关闭自动滚动调整 }, }, ], }} > {/* 菜单项 */} </Menu>
验证效果
测试时,先滚动页面让按钮部分移出屏幕,打开Menu并添加上方div,关闭Menu后页面不会再出现大幅滚动跳转。
内容的提问来源于stack exchange,提问作者Mitchy
相关产品推荐
相关产品推荐

