🐵 原生模态对话框了解一下?
在业务开发中,模态对话框(Modal Dialog)是常用的组件,主要用途是在用户处理重要事务/操作时,进行信息展示/二次确认⚠️等,而不用离开当前页面。
图为 Antd Modal
通常项目中我们会使用成熟框架提供的 Modal 组件,你是否知道,其实 HTML 5.2 (2018) 也提供了原生的 Dialog 元素。这篇文章就一起来学习如何使用原生 Dialog 吧。
Dialog
学习一个新知识点,最快的上手的方式是自己动手写 Demo,这里直接上代码看示例。
HTML 代码非常简单如下所示,之前你可能没听说过 dialog 标签,现在你应该知道了,它也是 HTMLElement 的子类 HTMLDialogElement。
<dialog class="modal" id="modal">
<div class="modal-content">
<div class="modal-header"><div class="modal-title">标题</div></div>
<div class="modal-body">
<p>正文...</p>
<p>正文...</p>
<p>正文...</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" id="cancel-btn"><span>取 消</span></button>
<button type="button" class="btn btn-primary" id="ok-btn"><span>确 定</span></button>
</div>
</div>
</dialog>
属性: open
默认情况下 dialog 元素不可见,除非给它加上 open 属性。
<dialog class="modal" id="modal" open>
...
</dialog>
浏览器自带的 stylesheet 会让 dialog 元素默认呈现水平居中效果。

方法: show/showModal/close
除了设置 open attribute,还可以调用 dialog 的 show/showModal/close 方法来让控制其展示与否。
$$.showBtn.addEventListener('click', () => {
$$.modal.show();
})
$$.showModalBtn.addEventListener('click', () => {
$$.modal.showModal();
})
$$.cancelBtn.addEventListener('click', () => {
$$.modal.close()
})
show 和 showModal 的区别是,show 只是 dialog 让元素可见(相当于设置 open=true),showModal 则会让 dialog 呈现模态效果,需要将模态框关闭之后才能和页面上其他元素交互。
落到具体实现上,当点击 showModal 时,浏览器会在 dialog 内部增加 ::backdrop 伪元素。
伪元素 ::backdroop
伪元素是啥?和 ::before/::after 是一类东西~
浏览器自带的 stylesheet 会让 ::backdrop 和 dialog 都变成 position: fixed,以达到遮盖页面其他元素的效果。

可以通过 ::backdrop 自定义这层遮罩的样式,就像这样。

事件:cancel/close
dialog 还提供了原生事件:
cancel在模态框展示时按下Esc按键,那么模态框将自动关闭,并触发cancel事件;close则是在每次dialog元素由open=true变为open=false时触发;
属性: returnValue
close 方法还支持接收一个参数,这个参数被赋值给 dialog.returnValue。
$$.okBtn.addEventListener('click', () => {
$$.modal.close('Ok')
})
$$.modal.addEventListener('close', () => {
// 在这里获取 returnValue 将读到 "Ok"
$$.result.innerHTML = $$.modal.returnValue
})
伪类 :modal
上面提到 showModal 方法被调用时,dialog 内会插入伪元素 backdrop,并且应用 position: fixed。而 dialog 元素本身的样式则是通过另一个伪类选择器 :modal

从 MDN 文档上看,:modal 伪类会匹配具有交互排它性的元素,例如模态框或者调用 requestFullscreen 方法的元素。
到这里, <dialog> 的知识普及环节就结束了。接下来我们尝试给它的出现/消失加上动画效果。
✨ Bonus
Bonus1 加入出现/消失动画
可以使用 :modal 伪类选择器来轻松实现模态框出现动画。
.modal:modal {
animation: fadeInUp 0.3s;
}
@keyframes fadeInUp {
}
消失动画则可以是监听 animationend event 来实现,在尝试关闭时触发关闭动画,将 dialog.close 方法放到消失动画结束再调用。
.modal.leaving {
animation: fadeOutDown 0.3s;
}
@keyframes fadeOutDown {
}
$$.modal.addEventListener('cancel', () => {
// $$.modal.close('Cancelled by event')
requestCloseModal('Cancelled by event')
})
function requestCloseModal (msg) {
$$.modal.classList.add('leaving')
$$.modal.addEventListener('animationend', () => {
$$.modal.close(msg)
$$.modal.classList.remove('leaving')
}, {
once: true
})
}
Bonus2 支持 maskClosable
日常使用时,还会希望点击遮罩时,模态框也能退出,dialog 不支持这样的 API。我们可以通过给 modal 添加点击事件,判断 event.target 来实现。
$$.modal.addEventListener('click', (event) => {
if (event.target === $$.modal) {
requestCloseModal('Cancelled by backdrop');
}
});
兼容性
当前(20220909) dialog 的浏览器支持率是 92.18%,不过 Chrome 团队也给出了 dialog-polyfill~

结束
又学到了一个新的知识点,祝大家中秋节🎑快乐。
相关链接
转载自:https://juejin.cn/post/7141271149559676942