🐵 原生模态对话框了解一下?
在业务开发中,模态对话框(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