如何正确控制HTML <dialog>模态对话框的关闭行为
核心原因
<dialog>的close事件是不可取消的,触发时机是模态框已经完成关闭动作之后,此时再调用e.preventDefault()不会产生任何拦截效果,自然没法阻止模态框关闭。
标准拦截方案
所有关闭拦截逻辑都需要在关闭动作真正执行前做判断,针对不同的关闭触发路径分别处理:
- 拦截ESC键触发的关闭:监听
cancel事件,这个事件在用户按ESC触发关闭、模态框还没真正关闭时触发,支持取消操作,只要在回调里判断不允许关闭时调用e.preventDefault()就能拦住 - 拦截点击遮罩触发的关闭:原生
<dialog>默认没有点击遮罩自动关闭的逻辑,如果你自己实现了这个交互,只需要在判断点击到遮罩层(即事件target是dialog元素本身)时,先校验关闭权限,符合允许关闭的条件再调用dialog.close()即可 - 拦截自定义关闭按钮触发的关闭:直接在按钮的点击回调里先做权限校验,满足关闭条件时再执行关闭方法就行
修正后的可运行示例
JS部分:
ReactDOM.render( <App />, document.getElementById("root") ); function App() { const modalRef = React.createRef() // 按业务需求修改关闭权限判断逻辑,示例为禁止关闭 const canClose = false function handleCancel(e) { if (!canClose) { e.preventDefault() console.log('当前场景下不允许关闭模态框') } } function handleDialogClick(e) { // 点击的是dialog根元素即遮罩区域 if (e.target !== modalRef.current) return if (!canClose) { console.log('当前场景下不允许关闭模态框') return } modalRef.current.close() } return( <React.Fragment> <button onClick={() => modalRef.current.showModal()}> Open modal </button> <dialog ref={modalRef} onCancel={handleCancel} onClick={handleDialogClick}> Hello world </dialog> </React.Fragment> ) }
HTML部分:
<div id='root'></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

