在我的 React 应用程序中,我使用了来自 material ui 的弹出组件。将鼠标悬停在图标上不会打开弹出窗口
In my React application, I'm using a popover component from material ui. Hovering over the icon does not open the popover
我无法弄清楚这一点。我已经实现了一个弹出窗口组件,当用户将鼠标悬停在 'i' 图标上时,弹出窗口应该打开,当用户将鼠标悬停在图标之外时,它应该关闭弹出窗口。我认为正在发生的事情是,将鼠标悬停在图标上时,会不断调用打开和关闭方法,因此它看起来从未打开过。
我的组件:
export const InfoIconWrapper = styled(InfoIcon)(({ theme }) => ({
color: fade(theme.palette.black, 0.3),
}));
export const GridWrapper = styled(Grid)(({ theme }) => ({
pointerEvents: 'none',
padding: theme.spacing(1),
}));
const DistributionLinePopover = ({ distributionLine }) => {
const [anchorEl, setAnchorEl] = useState(null);
const handlePopoverOpen = event => {
setAnchorEl(event.currentTarget);
};
const handlePopoverClose = () => {
setAnchorEl(null);
};
const open = Boolean(anchorEl);
const mouseOverPopover = 'mouse-over-popover';
return (
<Fragment>
<Typography
aria-owns={open ? mouseOverPopover : undefined}
aria-haspopup="true"
onMouseEnter={handlePopoverOpen}
onMouseOut={handlePopoverClose}
>
<InfoIconWrapper fontSize="small" />
</Typography>
<Popover
id={mouseOverPopover}
open={open}
anchorEl={anchorEl}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'left',
}}
// onMouseOut={handlePopoverClose}
disableRestoreFocus
>
<GridWrapper container>
...
</GridWrapper>
</Popover>
</Fragment>
);
};
如何修改此代码以使其按预期运行?最初我尝试将 handlePopoverClose 传递给 popover,但这使得只有当您将鼠标悬停在实际的 popover 上而不是悬停在远离 'i' 图标时,popover 才会关闭。
不要让 anchorElem existence 成为开放布尔状态值的一部分。事实上,您根本不需要检查 anchorElem。处理 DOM 元素引用时可能会出现竞争条件。
我会将 setAnchorEl
更改为 setOpen
,然后将 setOpen
更改为 true
。您可能希望使用 onClick 事件处理程序将 "X" 按钮设置为打开 false
。我认为从技术上讲,当一个新元素呈现在您悬停的元素之上时,底层元素会触发 "on mouse out"。见 this:
According to the browser logic, the mouse cursor may be only over a single element at any time – the most nested one and top by z-index.
好的,终于找到解决办法了。
在 Popover 组件中,将其添加为道具:style={{ pointerEvents: 'none' }}
并删除 onMouseOut。
在 InfoIconWrapper 组件中,将其添加为道具 onMouseLeave={handlePopoverClose}
按预期工作:)
我无法弄清楚这一点。我已经实现了一个弹出窗口组件,当用户将鼠标悬停在 'i' 图标上时,弹出窗口应该打开,当用户将鼠标悬停在图标之外时,它应该关闭弹出窗口。我认为正在发生的事情是,将鼠标悬停在图标上时,会不断调用打开和关闭方法,因此它看起来从未打开过。
我的组件:
export const InfoIconWrapper = styled(InfoIcon)(({ theme }) => ({
color: fade(theme.palette.black, 0.3),
}));
export const GridWrapper = styled(Grid)(({ theme }) => ({
pointerEvents: 'none',
padding: theme.spacing(1),
}));
const DistributionLinePopover = ({ distributionLine }) => {
const [anchorEl, setAnchorEl] = useState(null);
const handlePopoverOpen = event => {
setAnchorEl(event.currentTarget);
};
const handlePopoverClose = () => {
setAnchorEl(null);
};
const open = Boolean(anchorEl);
const mouseOverPopover = 'mouse-over-popover';
return (
<Fragment>
<Typography
aria-owns={open ? mouseOverPopover : undefined}
aria-haspopup="true"
onMouseEnter={handlePopoverOpen}
onMouseOut={handlePopoverClose}
>
<InfoIconWrapper fontSize="small" />
</Typography>
<Popover
id={mouseOverPopover}
open={open}
anchorEl={anchorEl}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'left',
}}
// onMouseOut={handlePopoverClose}
disableRestoreFocus
>
<GridWrapper container>
...
</GridWrapper>
</Popover>
</Fragment>
);
};
如何修改此代码以使其按预期运行?最初我尝试将 handlePopoverClose 传递给 popover,但这使得只有当您将鼠标悬停在实际的 popover 上而不是悬停在远离 'i' 图标时,popover 才会关闭。
不要让 anchorElem existence 成为开放布尔状态值的一部分。事实上,您根本不需要检查 anchorElem。处理 DOM 元素引用时可能会出现竞争条件。
我会将 setAnchorEl
更改为 setOpen
,然后将 setOpen
更改为 true
。您可能希望使用 onClick 事件处理程序将 "X" 按钮设置为打开 false
。我认为从技术上讲,当一个新元素呈现在您悬停的元素之上时,底层元素会触发 "on mouse out"。见 this:
According to the browser logic, the mouse cursor may be only over a single element at any time – the most nested one and top by z-index.
好的,终于找到解决办法了。
在 Popover 组件中,将其添加为道具:style={{ pointerEvents: 'none' }} 并删除 onMouseOut。
在 InfoIconWrapper 组件中,将其添加为道具 onMouseLeave={handlePopoverClose}
按预期工作:)