用现代 HTML 的原生原语替换你的 UI 库:模态对话框、互斥的手风琴、popover 和可编辑区域。
在 Kodokon 中打开本课<dialog> 原生地解决了多年来模态框库拼凑着实现的东西。showModal() 会把该元素投射进顶层(top layer) —— 位于任何 z-index 之上 —— 使文档的其余部分变得惰性(inert)(无法聚焦、无法点击),并暴露 ::backdrop 伪元素。而 show() 则显示一个非模态的对话框,没有惰性也没有背景遮罩。较新的 closedby=any 属性增加了点击外部即可关闭的功能。
<dialog id="confirm-dlg">
<form method="dialog">
<p>Delete this item?</p>
<button value="cancel">Cancel</button>
<button value="ok">Confirm</button>
</form>
</dialog>一个 <form method=dialog> 会在不发起网络提交的情况下关闭对话框:触发按钮的 value 会成为 dialog.returnValue,你可以在 close 事件中读取它。Escape 键会关闭一个模态对话框,方式是先发出 cancel 事件,如果输入正在进行中,你可以用 preventDefault() 取消它。
const dlg = document.getElementById("confirm-dlg");
dlg.showModal();
dlg.addEventListener("close", () => {
console.log(dlg.returnValue); // "ok" or "cancel"
});Popover API 无需 JavaScript 就能覆盖菜单、富提示框和 toast:把 popover 放在元素上、把 popovertarget 放在按钮上,浏览器就会处理好顶层、轻量关闭(light dismiss)(外部点击、Escape)以及 auto popover 之间的互相关闭。与 showModal() 不同,popover 不会让页面变得惰性。beforetoggle 和 toggle 事件让你可以取消或观察每一次过渡。
<button popovertarget="user-menu">Menu</button>
<div id="user-menu" popover>
<button>Profile</button>
<button>Log out</button>
</div><details> 无需脚本就提供了可访问的可折叠内容,而一个共享的 name 属性会创建一个互斥分组:打开一个就会关闭其他的。toggle 事件会在每次状态变化时触发。在编辑方面,contenteditable 把任何元素变成一个富文本输入区域;它的 plaintext-only 变体禁止任何标记,而 beforeinput 事件很好地替代了已废弃的 document.execCommand API。
<details name="faq" open>
<summary>Delivery time?</summary>
<p>Within 48 hours.</p>
</details>
<details name="faq">
<summary>Return policy?</summary>
<p>Within 30 days.</p>
</details>show(),showModal() 多带来了什么?<details> 上使用相同的 name 属性会产生什么?auto popover 和 manual popover 之间的行为差异是什么?