学习前提

理解表单按钮、DOM事件和键盘焦点;浏览器需支持原生dialog。

本课完成后你能做什么

使用dialog完成明确的确认流程,理解模态状态与普通可见状态的区别。

先理解机制

showModal把对话框放到顶层并阻止与同文档背景交互;普通open属性或show只表示可见,不提供相同的模态行为。使用原生机制可以减少自己维护遮罩、焦点限制与层叠的工作,但仍需要清晰标题与关闭入口。

把确认动作与关闭分开考虑。用户可能按Escape取消,也可能点击明确的取消按钮;只有确认结果才能执行对应操作。打开前清空旧returnValue,避免前次确认值在后续取消时被误读。示例操作只是改变练习文字,不删除实际数据。

method=dialog的表单提交会关闭对话框,不会按普通HTTP表单发送数据。按钮value可表达选择。焦点初始位置应帮助用户理解内容,关闭后回到发起按钮;较长说明不一定适合立即聚焦危险的确认动作。

::backdrop用于遮罩样式。不要假设点击遮罩必然关闭,默认行为与自己实现的轻点关闭要分开测试。对话框不是所有提示的首选,小型成功消息通常用状态文本就足够。

可运行示例

运行方式:将HTML示例保存为独立的.html文件并在浏览器打开;含脚本的示例使用现代浏览器。资源文件与多文件模块另按正文要求准备。

<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Honeysuck practice</title></head><body>
<button id="open">Reset practice score</button><p id="status" role="status">Score: 3</p>
<dialog id="confirm" aria-labelledby="dialog-title"><h2 id="dialog-title">Reset this practice?</h2><p>This only changes the demo score.</p>
<form method="dialog"><button value="cancel" autofocus>Keep score</button><button value="confirm">Reset</button></form></dialog>
<style>dialog{max-width:min(90vw,400px);border:1px solid #b9c9be;border-radius:12px}dialog::backdrop{background:#10251c88}</style>
<script>
const trigger=document.querySelector('#open'),dialog=document.querySelector('#confirm');
trigger.addEventListener('click',()=>{dialog.returnValue='';dialog.showModal();});
dialog.addEventListener('close',()=>{if(dialog.returnValue==='confirm')document.querySelector('#status').textContent='Score: 0';trigger.focus();});
</script>
</body></html>

推演与验证

打开后Tab应在对话框内部循环,背景按钮无法操作。点Keep score保持3;重新打开再点Reset变0。再次打开后按Escape,确认没有新的确认动作。每条路径关闭后焦点应返回发起按钮。

常见错误与边界

不要用全局z-index猜测来替代顶层机制。示例不做服务端操作,真实提交仍需等待结果并处理失败,不能在请求尚未成功时先宣称完成。

动手练习

增加重置原因输入,只有输入不少于5个非空白字符才允许确认,取消仍随时可用。

参考解法与理由

为确认路径校验输入;取消按钮使用formnovalidate跳过必填约束。不要让required阻断取消。关闭后是否保留草稿需明确设计,重开时根据该规则初始化。

进一步阅读