MUI Menu组件子菜单输入控件点击后快速失焦问题求助
问题场景
使用MUI的Menu组件构建菜单,点击菜单项时通过Popper弹出TextField、Select等输入控件,但操作控件时会快速失去焦点,无法正常输入或选择。
问题原因
- 点击
MenuItem时,MUI的Menu组件默认触发关闭逻辑,导致菜单容器失去焦点 Popper挂载在MenuItem内部,状态更新引发组件重渲染,破坏输入控件的焦点状态- 未正确处理事件传播,导致焦点被意外转移
解决方案
以下是修复后的代码:
import React, { useState } from "react"; import ReactDOM from "react-dom"; import { Button, Menu, MenuItem, Fade, Box, Popper, TextField } from "@material-ui/core"; import "./styles.css"; function App() { const [plusAnchorEl, setPlusAnchorEl] = useState(null); const [menuItemAnchorEl, setMenuItemAnchorEl] = useState(null); const [menuIndex, setMenuIndex] = useState(null); const handlePlusClick = (event) => { setPlusAnchorEl(prev => prev === null ? event.currentTarget : null); }; const handleMenuClick = (event, index) => { // 阻止事件冒泡和默认行为,避免Menu关闭 event.stopPropagation(); event.preventDefault(); setMenuItemAnchorEl(event.currentTarget); setMenuIndex(prev => prev === index ? null : index); }; const handleMenuClose = (event, reason) => { // 仅在点击外部或按下ESC时关闭菜单,操作控件时保持打开 if (reason === "backdropClick" || reason === "escapeKeyDown") { setPlusAnchorEl(null); setMenuItemAnchorEl(null); setMenuIndex(null); } }; return ( <> <Button onClick={handlePlusClick}>+</Button> <Menu anchorEl={plusAnchorEl} open={!!plusAnchorEl} onClose={handleMenuClose} anchorOrigin={{ vertical: "bottom", horizontal: "left" }} transformOrigin={{ vertical: "top", horizontal: "left" }} > <MenuItem key="1" onClick={(e) => handleMenuClick(e, "One")}> One </MenuItem> <MenuItem key="2" onClick={(e) => handleMenuClick(e, "Two")}> Two </MenuItem> </Menu> {/* 将Popper移出Menu内部,避免重渲染影响 */} {menuIndex === "One" && ( <Popper open={!!menuItemAnchorEl && menuIndex === "One"} placement="right-end" anchorEl={menuItemAnchorEl} transition > {({ TransitionProps }) => ( <Fade {...TransitionProps} timeout={350}> <Box p={2} bgcolor="background.paper" boxShadow={3}> <TextField placeholder="输入内容" /> </Box> </Fade> )} </Popper> )} {menuIndex === "Two" && ( <Popper open={!!menuItemAnchorEl && menuIndex === "Two"} placement="right-end" anchorEl={menuItemAnchorEl} transition > {({ TransitionProps }) => ( <Fade {...TransitionProps} timeout={350}> <Box p={2} bgcolor="background.paper" boxShadow={3}> <TextField select> <MenuItem key="2.1">Two.One</MenuItem> <MenuItem key="2.2">Two.Two</MenuItem> </TextField> </Box> </Fade> )} </Popper> )} </> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
关键修改点说明
- 事件处理:在
handleMenuClick中添加event.stopPropagation()和event.preventDefault(),阻止点击MenuItem时触发Menu的关闭逻辑 - Popper位置调整:将
Popper从MenuItem内部移到外部,避免MenuItem重渲染导致Popper销毁重建 - Menu关闭逻辑优化:在
handleMenuClose中判断关闭原因,仅在点击外部或按下ESC时关闭菜单,操作输入控件时保持菜单和Popper打开 - 状态管理优化:简化状态切换逻辑,避免不必要的状态更新
内容的提问来源于stack exchange,提问作者GRZa
相关产品推荐
相关产品推荐

