showModal() 是唯一真正实现交互阻塞的原生方式;alert() 非模态因不渲染于 DOM、不可定制、移动端受限;dialog.showModal() 需满足:body 直接子节点、无干扰 CSS、DOM 就绪;关闭后需用 formmethod="dialog" 按钮或显式 close() 设置 returnValue;须手动管理焦点、aria-hidden 和复用清理。

showModal() 是唯一能真正实现交互阻塞的原生方式,其他写法(包括 alert()、dialog.show() 或手动设 open 属性)都不满足“运行时模态交互”要求。
为什么 alert() 不算模态提示?
alert() 确实会阻塞 JS 执行,但它不是模态框——它不渲染在页面 DOM 中,无法定制样式、内容结构或按钮文案;移动端常被系统拦截;不支持 HTML、焦点管理或无障碍属性。它只是浏览器级提示,和 UI 交互无关。
dialog.showModal() 必须满足的三个硬性条件
缺一不可,否则 backdrop 不生效、背景仍可点击、Tab 键穿透:
-
<dialog></dialog>元素必须是的直接子节点——动态创建时务必用document.body.appendChild(dialog) - 不能嵌套在任何设置了
transform、overflow、position: relative的父容器里,否则 Chrome/Safari 可能丢弃::backdrop - 调用前确保 DOM 已就绪,且不能依赖框架挂载逻辑(如 React 的
createPortal若没挂到body下一级,就失效)
关闭后如何读取用户操作意图?
dialog.returnValue 只在特定条件下自动赋值:必须用 <button formmethod="dialog" value="confirm"></button> 这类表单提交式按钮,普通 click 不会设置它。可靠做法是:
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 给确认/取消按钮分别加
value="confirm"和value="cancel" - 监听按钮点击,显式调用
dialog.close(button.value) - 在
dialog.addEventListener('close', () => console.log(dialog.returnValue))中读取结果 - 避免写
onclick="dialog.close('confirm')",统一用事件委托或addEventListener
焦点陷阱和可访问性最容易漏掉的点
即使 showModal() 成功执行,若对话框内没有可聚焦元素(比如只有 <p></p> 和 <span></span>),焦点会落在 body 上,Tab 键直接切出弹窗。必须:
立即学习“前端免费学习笔记(深入)”;
- 第一个按钮加
autofocus,或 JS 中手动firstBtn.focus() - 监听
keydown捕获 Tab,实现焦点循环(首尾衔接) - 关闭后,用
triggerBtn.focus()把焦点还回去,而不是任由它留在别处 - 不要只靠
aria-modal="true",要配合给背景容器设aria-hidden="true"(但别设在上)


















