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

如何处理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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:10:20