关于前端:你可能不知道的dialog弹窗

10次阅读

共计 4046 个字符,预计需要花费 11 分钟才能阅读完成。

欢送关注我的公众号:前端侦探

想必大家都晓得 HTML5 中有 dialog 这样一个标签,顾名思义,就是“弹窗”。除了有良好的语义外,随着浏览器的不断更新迭代,还呈现了许多你可能不晓得的个性,疾速理解一下吧~

一、关上和敞开办法

首先,在不查阅任何官网文档的状况下,先做一个抉择题目

请问:上面哪组办法(关上 / 敞开)是非法的?

思考 10 秒 …

🤔

🤔

🤔

🤔

正确答案是 C,也就是

// 关上弹窗
dialog.show()
// 关上敞开
dialog.close()

很多同学可能会感觉是 A 或者 B,然而官网文档上确是 C,的确是一个令人蛊惑的办法。至于起因,有解释说,dialog是存在于页面上的元素,所以关上用show,而敞开示意中断弹窗内的行为,所以用close,只能说有分割,但比拟牵强,或者就是标准设计忽略了,大家记住就好。

还有一个,如果须要弹窗默认显示,大家先猜猜看?

再来思考 10 秒 …

🤔

🤔

🤔

🤔

正确答案是 B,也就是

<dialog open></dialog>

🤣是不是又和下面的 show() 对不上了?

除了 dialog 元素,details元素的关上属性也是open

二、表单提交个性

弹窗很多时候的作用都是充当表单输出。

比方一个弹窗中须要有一个敞开或者勾销按钮

<dialog>
  <h3> 欢送关注前端侦探 </h3>
  <button> 敞开 </button>
</dialog>

通常状况下,咱们可能须要用到后面提到的 dialog.close() 办法来被动敞开弹窗。

其实,还能够通过表单个性实现这样一个成果,具体做法是:

  1. dialog 中嵌套一层form
  2. form 增加一个 method=dialog 属性

如下

<dialog>
  <form method="dialog">
    <h3> 欢送关注前端侦探 </h3>
    <button> 敞开 </button>
  </form>
</dialog>

这样就 能够不必绑定额定的事件来实现敞开性能 了,成果如下

其实起因就在于表单上的 method=dialog 属性,如果表单在 dialog 元素中,提交时就会触发敞开对话框

https://developer.mozilla.org…

默认状况下,表单里的 button 都会触发提交,等同于 type=submit,但如果设置了type=button 或者type=reset,则不会触发表单提交,天然也不会敞开弹窗

<dialog>
  <form method="dialog">
    <h3> 欢送关注前端侦探 </h3>
    <button> 敞开 </button>
    <button type="button"> 不会敞开 </button>
  </form>
</dialog>

成果如下

另外还有一个小个性,dialog还有一个 returnValue 属性,能够返回表单中提交按钮的 value

<dialog>
  <form method="dialog">
    <h3> 欢送关注前端侦探 </h3>
    <button value="AAA"> 提交 </button>
  </form>
</dialog>

在提交后能够打印弹窗的returnValue,如下

不过临时还没有想到很有用的场景

三、模态窗口个性

弹窗除了能够通过 dialog.show() 关上之外,还提供了一个模态窗口,办法是

dailog.showModal()

通过这个办法关上的弹窗,会自带一个半透明的背景,并且齐全程度垂直居中

这个半透明的背景并不是一般的元素,而是一个叫做::backdrop 的伪元素管制的,并且目前只有通过 dailog.showModal() 这个办法能力生成

要自定义背景也很容易

dialog::backdrop {background: rgba(255,0,0,.25);
}

这样就变成了半透明红色

如果心愿关上弹窗有动画,能够自定义默认款式,通过 visibility 的形式实现暗藏显示

dialog{
  position: fixed;
  margin: auto;
  inset: 0;
  width: fit-content;
  height: fit-content;
  display: block;
  visibility: hidden;
  opacity: 0;
  transform: translateY(100px);
  transition: .2s;
}
dialog[open] {
  visibility: visible;
  opacity: 1;
  transform: translateY(0);
}

成果如下

其实这里我是不太倡议动画的,弹窗就是要反馈疾速,加了动画反而会连累整体。

另外,还能够通过 :modal 伪类来辨别是一般弹窗还是模态弹窗

dialog:modal{/* 模态弹窗 */}
dialog:not(:modal){/* 一般弹窗 */}

这样能够更多进行自定义行为

模态弹窗还有一个十分省心的点,就是无需关注层级。它有一套十分直观的规定,哪个后关上,哪个层级最高,比方这样两个弹窗

<dialog id="dialog2">
  ...
</dialog>
<dialog id="dialog1">
  ...
  <button type="button"> 关上弹窗 2 </button>
  ...
</dialog>

在不指定层级的状况下,必定是前面的层级更高,但如果是通过 dialog.showModal 关上,就十分直观了,后关上的弹窗必定会笼罩后面的,成果如下

说到这里,我又想到了一些 UI 组件库里大到可怕的z-index,大概率就是通过计算得出的

四、焦点隔离个性

除了下面一些比拟直观的个性外,还有一些可能会疏忽的,比方焦点的管制。

默认状况下,关上弹窗后会主动聚焦到弹窗内的第一个可聚焦元素上

还能够有 input 输入框

<dialog>
  <form method="dialog">
    <h3> 欢送关注前端侦探 </h3>
    <input name="txt">
    <button> 敞开 </button>
  </form>
</dialog>

关上弹窗后能够间接输出,无需额定操作,几乎不要太不便

留神,留神,留神:经测试发现,如果增加了关上动画,聚焦个性就会生效

当然,这些只是小儿科,一点点额定的 JS 也能解决,上面介绍一个零碎级别的 焦点隔离个性 。什么意思呢?就是说在关上弹窗后,弹窗就成了一个独立的载体,焦点只能在这个范畴内挪动,也就是说,无论tab 键如何切换,焦点不会跑到弹窗里面去,上面是一个比照成果

  1. 一般弹窗成果
  1. 模态弹窗成果

这个成果其实是和新出的 inert 属性作用比拟相似的,然而要比 inert 呈现的更早,也能够说是通过 inert 属性将这种隔离个性通用化了,让平民老百姓也能够享受这种高级个性。有趣味的能够拜访我之前的这篇文章:疾速理解 inert 属性

五、顶层个性 top-layer

最初介绍一个即使是 JS 也无奈模仿的零碎级新个性,top-layer

不晓得大家有没有遇到这样的问题,有些弹窗因为业务须要,不得已写在了某些容器上面,即使是 fixed 定位,也会有生效的时候,比方上面这个例子,父容器如果有 transform 相干属性并且超出暗藏,就会呈现这样被裁剪的情景

下面这个例子来源于 xy-ui 中的 dialog 组件,后续优化,敬请期待~

在以前,或者说很多框架中,都会想方法把弹窗放到最外层的 body下,这样就不受影响了,比方上面是 vue3 中的解决形式

<div>
  <Teleport to="body"> <!-- 将子内容传送到 body 下 -->
      <dialog></dialog>
  </Teleport>
</div>

但当初,有了全新的 top-layer,所有都好办了,比方上面是一个通过 dialog.showModal() 关上的弹窗

你会发现,尽管 dialog 依然在原来地位上,但真正渲染到了一个 #top-layer 的层级上,这个层级十分非凡,曾经超过了 html 文档流,能够说是独一档的存在,这样,无论的 dialog 在什么地位,最初渲染的中央其实都在 #top-layer 层级上,天然也不会被父容器裁剪被暗藏了,示意如下

是不是和古代框架有些许相似呢?上面是一个弹窗里嵌套另外一个弹窗

<dialog id="dialog1">
  ...
  <button type="button" > 关上弹窗 2 </button>
  <dialog id="dialog2">
        ...
  </dialog>
</dialog>

成果如下

其实这也是后关上的弹窗永远要高于之前弹窗的起因,#top-layer是动态创建的,只有关上的弹窗才会渲染到该层级之下。

另外,经测试发现,firefox 以及 safari 尽管在开发者工具上看不到 #top-layer,然而dialog 体现根本简直统一,应该是曾经成为了标准规范,日后能够放心使用。

六、dom 其实也是在一直倒退的

dialog其实我在两三年之前就有钻研过,那时还没有这么多新个性,也有可能是钻研不精,起初就搁置了,而后最近在我的项目中用了dialog,无心中又发现了很多有意思的新个性,这意味着,dom 其实也是在一直倒退的,有必要把以前曾经用过的再翻出来过一遍,说不定还能发现意想不到的后果,上面是要点总结

  1. dialog 的关上和敞开办法很蛊惑,别离是show() / close()
  2. dialog中表单元素在增加 method=dialog 属性之后,只有触发表单提交就会主动敞开弹窗,无需额定 js
  3. 通过 showModal() 能够关上模态弹窗,并且后关上的弹窗永远比先关上的弹窗层级要高,无需手动计算层级
  4. 关上弹窗会主动聚焦到弹窗内的第一个可聚焦元素,不便疾速输出
  5. 模态弹窗的焦点不会聚焦到弹窗内部,这和 inert 个性比拟相似
  6. 模态弹窗其实是渲染到了 html 文档流之外,一个叫 #top-layer 的层级上,因而不会受到原父容器的影响

很多同学往往过于关注 JavaScript和古代风行框架,而漠视了原生 dom 的倒退,但原生 dom 带来的很多新个性往往是零碎级别的,有可能你辛辛苦苦实现的一个性能,原生一个属性就搞定,而且成果更好,所以请不要忘了原生。最初,如果感觉还不错,对你有帮忙的话,欢送 点赞、珍藏、转发❤❤❤

欢送关注我的公众号:前端侦探

正文完
 0