Material UI关闭Dialog后打开按钮残留focus状态如何解决
问题原因说明
这个行为不是Material UI的bug,是默认遵循WAI-ARIA无障碍规范的设计:模态弹窗关闭后必须将焦点返还给触发弹窗的元素,目的是保障键盘导航用户的操作体验。你看到的:focus状态残留就是焦点返还后的正常表现。
官方解决方案
Material UI的Dialog组件原生提供了disableRestoreFocus配置项,直接设置为true即可完全禁用关闭后自动回焦的行为,不需要手动处理ref和blur逻辑,也不会出现样式闪烁问题。
单Dialog配置示例
const useStyles = makeStyles({ root: { "&:focus": { backgroundColor: "#3A7DA9" } } }); export default function App() { const [open, setOpen] = useState(false); const classes = useStyles(); return ( <div className="App"> <Button id="button-that-opens-modal" className={classes.root} onClick={() => setOpen(true)} > 打开模态框 </Button> {/* 核心配置:添加disableRestoreFocus={true} */} <Dialog open={open} disableRestoreFocus={true}> <h3>这是一个模态框</h3> <Button onClick={() => setOpen(false)}> 关闭 </Button> </Dialog> </div> ); }
全局统一配置(适合多Dialog场景)
如果项目中存在大量Button-Dialog组合,不需要逐个加属性,可以在主题配置中全局修改Dialog的默认属性:
import { createTheme, ThemeProvider } from '@mui/material/styles'; const theme = createTheme({ components: { MuiDialog: { defaultProps: { disableRestoreFocus: true, }, }, }, }); // 项目根组件包裹ThemeProvider即可全局生效 function Root() { return ( <ThemeProvider theme={theme}> <App /> </ThemeProvider> ); }
原手动方案闪烁原因说明
你之前用onExited回调手动blur的方案出现闪烁,是因为Dialog的焦点返还逻辑在过渡动画开始前就执行了,而onExited是过渡动画完全结束后才触发,中间会有短暂的时间窗口显示:focus样式,所以会出现闪烁,使用官方配置项不会有这个问题。
内容的提问来源于stack exchange,提问作者Seth Lutske
相关产品推荐
相关产品推荐

