自 1995 年 JavaScript 誕生之初,就包含了 3 個方法 alert()
、confirm()
和 prompt()
。在隨後的 Chrome 版本中,Chrome 團隊一直在修改原生彈窗的表現。
但是這種阻斷式的彈窗總被各種廣告網站惡意使用,因為只要彈窗出現,JavaScript 引擎就會一直等待,知道使用者操作。所以這種原生彈窗的最大用處不是用來提示使用者資訊,而是傷害使用者(Tech support scammers use subdomain trick to defeat blocking)。
因此 Chromium 團隊強烈建議你不要使用這類彈窗。
而彈窗和 onbeforeunload
事件相結合之後那簡直就是大殺器,而此類彈窗經常被用來提示瀏覽者xxxx。
Chromium 團隊在 Chrome 51 中移除了對 onbeforeunload
彈窗的支援。在此之前 Safari 9.1 和 Firefox 4 早就已經移除了。當我們在 onbeforeunload
事件中呼叫 alert
時,會在 devtools 中產生警告:
Blocked alert('before unload') during beforeunload.複製程式碼
除此之外,alert()
、confirm()
、prompt()
的行為也做了改變,不再作為頂級的原生彈窗而存在,當彈窗所在的瀏覽器標籤被切走後,它們會自動消失。(Safari 9.1 說:“你怎麼到現在才來學啊!”)
Chromium 在官方部落格中說到:
對於
alert()/confirm()/prompt()
我們有很多替代的選擇。 譬如需要彈個通知訊息時(日曆應用)可以用Notifications API。 獲取使用者輸入可以用 HTML 中的<dialog>
元素。 對於 XSS proofs-of-concept 則可用console.log(document.origin)
。
<dialog>
作為 HTML 5.2 的元素,目前除了 Chrome 和 Opara 以外,其它瀏覽器均未支援。但是 Google 提供了一個 dialog-polyfill。
一個最簡單的例子:
<dialog>This is da dialog!</dialog>複製程式碼
這段 html 什麼也不顯示,開發者需要使用 javascript 的 API .show()
和 .close()
來控制 dialog 的顯示和隱藏。
<dialog>
<p>This is da dialog!</p>
<button id="close">Close</button>
</dialog>
<button id="show">Open Dialog!</button>複製程式碼
var dialog = document.querySelector('dialog');
document.querySelector('#show').onclick = function() {
dialog.show();
};
document.querySelector('#close').onclick = function() {
dialog.close();
};複製程式碼
點選按鈕會出現一個彈窗(非常醜)
不過 dialog 作為一個 html 標籤,是可以使用 css 的。我們給它加一段 css 樣式:
dialog {
border: 1px solid rgba(0, 0, 0, 0.3);
border-radius: 6px;
box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
}複製程式碼
再點選按鈕,彈窗了一個稍微漂亮點的彈窗:
我們還可以使用 .showModal()
彈窗一個模態對話方塊,當我們關閉彈窗時觸發 close
事件。我們還可以使用 ESC 鍵關閉一個彈窗,此時會觸發 cancel
事件。和其它所有事件一樣,我們可以通過呼叫 event.preventDefault()
來阻止預設行為。
直接彈窗一個模態視窗是不夠友好的,有時我們需要把背景虛化:
通過使用 CSS 的偽元素 ::backdrop
很容易就可以做到:
dialog::backdrop {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.8);
}複製程式碼
為什麼使用 <dialog>
元素而不是第三方的 javascript 庫?
我覺得兩者並不衝突,目前大部分 javascript 庫都是使用 <div>
來模擬彈窗,當更多的瀏覽器開始支援 <dialog>
時,第三方的 javascript 庫也會考慮使用 <dialog>
作為首先的彈窗方式的,畢竟 <dialog>
是 HTML 5.2 規範中的。
相比 <div>
而言,<dialog>
更大強大,也更加符合規範。比如 <dialog>
的模態彈窗可以保證即使全屏的情況下,彈窗可以保持在最頂層(top-layer)。top-layer 定義在 whatwg 的 Fullscreen API 中,可以配合偽元素 ::backdrop
以及偽類 :fullscreen
一起使用。
開發面向未來的前端,當有 polyfill 方案時,我們應該總是使用最新標準。