如何阻止MUI Dialog内部操作时关闭(仅点击背景可关闭)
问题解决:阻止MUI Dialog点击内部区域时关闭
问题根源
你的Dialog被嵌套在触发它显示的<div onClick={() => setDisplay(true)}>元素内部,点击Dialog内的输入框、按钮等元素时,事件会冒泡到外层的触发div,同时触发Dialog的关闭逻辑,导致对话框意外关闭。
解决方案
以下两种方案任选其一即可解决问题:
方案一:将Dialog移出触发元素的嵌套结构
把Dialog从触发它的div中分离出来,避免事件冒泡影响状态:
import { Avatar, Button, Dialog, DialogContent, DialogTitle, MenuItem, TextField } from '@mui/material' import React, { useState } from 'react' const Entry = ({ entry, index, waypoints }) => { const [display, setDisplay] = useState(false); const [dataToParse, setDataToParse] = useState({ start: { index:'', from:'', to:'' }, end: { index:'', from:'', to:'' } }) return ( <> {/* 触发Dialog的元素单独分离 */} <div onClick={() => setDisplay(true)}> <Avatar style={{ marginLeft: '10px', width: '15px', height: '15px', background: 'green', fontSize: '12px' }}> {index} </Avatar> </div> {/* Dialog独立于触发元素之外 */} <Dialog open={display} aria-labelledby="alert-dialog-title" aria-describedby="alert-dialog-description" onClose={() => setDisplay(false)} disableEscapeKeyDown > <DialogTitle id="alert-dialog-title"> Edit this entry </DialogTitle> <DialogContent> <div style={{display:'flex', flexDirection:'column', width:'100%'}}> <p>Start: <strong>{entry.start.from} to {entry.start.to} </strong></p> <TextField select label="Starting Waypoint" fullWidth > {waypoints.map((option, index) => ( <MenuItem key={index +1} value={index +1} onClick={() => setDataToParse({ ...dataToParse, start: {index: index+1, from: option.from, to: option.to} })}> {option.from} to {option.to} </MenuItem> ))} </TextField> <p>End: <strong>{entry.end.from} to {entry.end.to} </strong></p> <TextField select label="Ending Waypoint" fullWidth > {waypoints.map((option, index) => ( <MenuItem key={index +1} value={index +1} onClick={() => setDataToParse({ ...dataToParse, end: {index: index+1, from: option.from, to: option.to} })}> {option.from} to {option.to} </MenuItem> ))} </TextField> <Button>Save</Button> </div> </DialogContent> </Dialog> </> ) } export default Entry
方案二:在Dialog内部阻止事件冒泡
在DialogContent上添加事件阻止冒泡的逻辑,让内部点击事件不会传到外层触发div:
<DialogContent onClick={(e) => e.stopPropagation()}> {/* 原Dialog内部内容保持不变 */} </DialogContent>
额外优化(可选)
如果你希望严格控制只有点击背景时才关闭Dialog,可以通过onClose的reason参数做判断:
<Dialog open={display} aria-labelledby="alert-dialog-title" aria-describedby="alert-dialog-description" onClose={(event, reason) => { // 仅当点击背景时关闭Dialog if (reason === 'backdropClick') { setDisplay(false); } }} disableEscapeKeyDown > {/* Dialog内容 */} </Dialog>
内容的提问来源于stack exchange,提问作者Calin Onaca
相关产品推荐
相关产品推荐

