Material UI如何实现点击时仅打开对应单个下拉菜单而非全部展开
问题根源
你当前所有下拉菜单共用全局的open = Boolean(anchorEl)判断逻辑,循环渲染的所有Menu组件只要检测到anchorEl有值就会被判定为展开状态,没有区分当前点击的具体菜单项,因此点击任意按钮都会触发所有菜单同步展开。
修复方法
新增状态存储当前激活菜单的唯一标识,仅当锚点元素存在 且 菜单标识与当前激活标识匹配时,才展开对应菜单。
需要调整的细节:
- 新增
activeMenuId状态,记录被点击的菜单ID - 点击事件触发时,同时保存锚点元素和对应菜单的ID
- 菜单关闭时,同时清空锚点元素和激活菜单ID
- 每个菜单的展开状态、按钮的无障碍属性(
aria-controls/aria-expanded)都要基于当前菜单自身的匹配状态判断,不能复用全局统一的open值 - 循环渲染的根节点不要使用无key的空标签,替换为带
key属性的React.Fragment,避免React抛出key缺失警告
修正后的完整代码:
const NavBarMainMenu = () => { const [anchorEl, setAnchorEl] = useState(null) const [activeMenuId, setActiveMenuId] = useState(null) // 判断指定ID的菜单是否处于展开状态 const isCurrentMenuOpen = (menuId) => Boolean(anchorEl) && activeMenuId === menuId const handleClick = (event, menuId) => { setAnchorEl(event.currentTarget) setActiveMenuId(menuId) } const handleClose = () => { setAnchorEl(null) setActiveMenuId(null) } return ( <Box sx={{ flexGrow: 1, display: { xs: "none", lg: "flex" } }}> {pages.map(page => { const menuOpen = isCurrentMenuOpen(page.title) return ( <React.Fragment key={page.title}> <Button id={`${page.title}-button`} onClick={(e) => handleClick(e, page.title)} aria-controls={menuOpen ? page.title : undefined} aria-haspopup="true" aria-expanded={menuOpen ? "true" : undefined} > {page.title} </Button> <Menu anchorEl={anchorEl} id={page.title} open={menuOpen} onClose={handleClose} onClick={handleClose} transformOrigin={{ horizontal: "right", vertical: "top" }} anchorOrigin={{ horizontal: "right", vertical: "bottom" }} > {page.children.map(child => ( <MenuItem key={child.title}>{child.title}</MenuItem> ))} </Menu> </React.Fragment> ) })} </Box> ) }
内容的提问来源于stack exchange,提问作者JeremyE
相关产品推荐
相关产品推荐

