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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 09:21:03