如何在数据保存时阻止Modal点击外部或失焦关闭?
解决方法
针对你在数据保存时阻止点击Modal外部关闭的需求,基于你使用的@headlessui/react Dialog组件,有两种简单的实现方式:
方式一:通过onClose回调判断关闭原因
Dialog的onClose回调会接收event和reason两个参数,其中reason代表关闭触发的原因——backdropClick对应点击外部遮罩,escapeKeyDown对应按ESC键。你可以在回调里判断当前是否处于保存状态,若是点击外部触发的关闭,就跳过关闭逻辑。
修改后的代码示例:
// 先定义一个状态标记是否正在保存 const [isSaving, setIsSaving] = useState(false); // 自定义关闭处理函数 const handleClose = (event, reason) => { // 保存过程中且是点击外部遮罩时,不执行关闭 if (isSaving && reason === 'backdropClick') return; params.toggleBooking(); }; // 渲染Dialog部分 <Transition.Root show={params.isOpen} as={Fragment}> <Dialog as="div" className="relative z-10" onClose={handleClose}> <Transition.Child as={Fragment} enter="ease-out duration-300" enterFrom="opacity-0" enterTo="opacity-100" leave="ease-in duration-200" leaveFrom="opacity-100" leaveTo="opacity-0" > <div className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity"/> </Transition.Child> {/* 你的Modal内容,比如表单和保存按钮 */} <button onClick={() => { setIsSaving(true); // 调用后端保存接口,完成后重置保存状态 yourSaveApiCall().finally(() => setIsSaving(false)); }} > {isSaving ? '保存中...' : '保存'} </button> </Dialog> </Transition.Root>
方式二:动态禁用遮罩的点击事件
在保存状态下,给遮罩层添加pointer-events-none类,让点击事件无法触发遮罩的关闭逻辑:
<Transition.Child as={Fragment} enter="ease-out duration-300" enterFrom="opacity-0" enterTo="opacity-100" leave="ease-in duration-200" leaveFrom="opacity-100" leaveTo="opacity-0" > <div className={`fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity ${isSaving ? 'pointer-events-none' : ''}`} /> </Transition.Child>
这种方法只会阻止点击外部遮罩的关闭,如果你需要同时禁用ESC键关闭,还是要结合方式一的reason === 'escapeKeyDown'判断。
内容的提问来源于stack exchange,提问作者FailedUnitTest
相关产品推荐
相关产品推荐

