如何处理Material UI中的多个Popover?实现点击仅打开对应弹窗
解决Material UI多个Popover同时打开的问题
嘿,我明白你遇到的问题了!现在两个Popover同时打开的原因很简单——你用了同一个anchorEl状态变量来控制它们的显示状态。不管点击哪个按钮,这个变量都会被设置成当前点击的元素,导致两个Popover都检测到anchorEl不为null,所以一起弹出来了。
下面给你两种可行的解决方案,你可以根据自己的场景选择:
方案一:为每个Popover单独设置状态变量
这种方式简单直接,适合Popover数量不多的场景,每个Popover用独立的状态来控制:
首先修改你的状态定义:
// 为每个Popover创建独立的anchorEl状态 const [anchorElMenu2, setAnchorElMenu2] = React.useState<null | HTMLElement>(null); const [anchorElMenu4, setAnchorElMenu4] = React.useState<null | HTMLElement>(null);
然后为每个按钮和Popover编写单独的处理函数:
// Menu 2的点击和关闭处理 const handleMenu2Click = (event: React.MouseEvent<HTMLButtonElement>) => { setAnchorElMenu2(event.currentTarget); }; const handleMenu2Close = () => { setAnchorElMenu2(null); }; // Menu 4的点击和关闭处理 const handleMenu4Click = (event: React.MouseEvent<HTMLButtonElement>) => { setAnchorElMenu4(event.currentTarget); }; const handleMenu4Close = () => { setAnchorElMenu4(null); };
最后更新Tab和Popover的绑定:
<Tabs variant="fullWidth" value={value} onChange={onNavChange} indicatorColor="transparent"> <Tab label="Menu 1" className={classes.navTab} component={Link} to="./Menu1"></Tab> {/* 绑定Menu2的点击事件 */} <Tab label="Menu 2" onClick={handleMenu2Click} aria-describedby="menu2Popover" aria-haspopup="true"></Tab> <Tab label="Menu 3" component={Link} to="./Menu3"></Tab> {/* 绑定Menu4的点击事件 */} <Tab label="Menu 4" onClick={handleMenu4Click} aria-describedby="menu4Popover" aria-haspopup="true"></Tab> </Tabs> {/* Menu2的Popover,用自己的状态控制显示 */} <Popover id="menu2Popover" open={Boolean(anchorElMenu2)} onClose={handleMenu2Close} anchorEl={anchorElMenu2} anchorOrigin={{ vertical: 'top', horizontal: 'left' }} transformOrigin={{ vertical: 'bottom', horizontal: 'left' }} > <MenuList> <MenuItem>Submenu 1</MenuItem> <MenuItem>Submenu 2</MenuItem> </MenuList> </Popover> {/* Menu4的Popover,用自己的状态控制显示 */} <Popover id="menu4Popover" open={Boolean(anchorElMenu4)} onClose={handleMenu4Close} anchorEl={anchorElMenu4} anchorOrigin={{ vertical: 'top', horizontal: 'left' }} transformOrigin={{ vertical: 'bottom', horizontal: 'left' }} > <MenuList> <MenuItem>Submenu 3</MenuItem> <MenuItem>Submenu 4</MenuItem> </MenuList> </Popover>
方案二:用单个状态标识当前激活的Popover
如果以后可能需要添加更多Popover,这种方式更灵活,只需要维护一个状态来记录当前打开的Popover ID:
首先修改状态定义:
// 记录当前激活的Popover ID,没有则为null const [activePopoverId, setActivePopoverId] = React.useState<string | null>(null); // 仍然保留anchorEl来定位Popover const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
然后编写通用的点击和关闭处理函数:
// 点击时传递对应Popover的ID const handleClick = (event: React.MouseEvent<HTMLButtonElement>, popoverId: string) => { setAnchorEl(event.currentTarget); setActivePopoverId(popoverId); }; // 关闭时清空状态 const handleClose = () => { setActivePopoverId(null); setAnchorEl(null); };
最后更新Tab和Popover的绑定:
<Tabs variant="fullWidth" value={value} onChange={onNavChange} indicatorColor="transparent"> <Tab label="Menu 1" className={classes.navTab} component={Link} to="./Menu1"></Tab> {/* 点击时传递menu2Popover的ID */} <Tab label="Menu 2" onClick={(e) => handleClick(e, "menu2Popover")} aria-describedby="menu2Popover" aria-haspopup="true"></Tab> <Tab label="Menu 3" component={Link} to="./Menu3"></Tab> {/* 点击时传递menu4Popover的ID */} <Tab label="Menu 4" onClick={(e) => handleClick(e, "menu4Popover")} aria-describedby="menu4Popover" aria-haspopup="true"></Tab> </Tabs> {/* 只有activePopoverId等于当前ID时才打开 */} <Popover id="menu2Popover" open={activePopoverId === "menu2Popover"} onClose={handleClose} anchorEl={anchorEl} anchorOrigin={{ vertical: 'top', horizontal: 'left' }} transformOrigin={{ vertical: 'bottom', horizontal: 'left' }} > <MenuList> <MenuItem>Submenu 1</MenuItem> <MenuItem>Submenu 2</MenuItem> </MenuList> </Popover> <Popover id="menu4Popover" open={activePopoverId === "menu4Popover"} onClose={handleClose} anchorEl={anchorEl} anchorOrigin={{ vertical: 'top', horizontal: 'left' }} transformOrigin={{ vertical: 'bottom', horizontal: 'left' }} > <MenuList> <MenuItem>Submenu 3</MenuItem> <MenuItem>Submenu 4</MenuItem> </MenuList> </Popover>
两种方案都能解决你的问题,方案一适合少量固定的Popover,方案二更易于扩展。你可以根据自己的需求选择~
内容的提问来源于stack exchange,提问作者shiva
相关产品推荐
相关产品推荐

