亚洲乱色熟女一区二区三区丝袜,天堂√中文最新版在线,亚洲精品乱码久久久久久蜜桃图片,香蕉久久久久久av成人,欧美丰满熟妇bbb久久久

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

原生<dialog>元素:別再自己手寫Modal彈窗了!

freeflydom
2025年8月5日 9:55 本文熱度 1244

Modal彈窗,可以說是我們前端UI界面里的“標配”了。但這個組件,恰恰是團隊里代碼質量的“重災區(qū)”。

我見過太多用div手寫的彈窗了:z-index滿天飛、焦點管理一塌糊涂、背景頁面還能滾動、Esc鍵也關不掉……這些問題,每一個都是體驗上的硬傷。

所以,最近我們團隊的新項目,我立了一個規(guī)矩:只要是做模態(tài)對話框,一律優(yōu)先使用原生的<dialog>元素。

它不僅能解決上面所有問題,而且代碼量少得驚人。這篇文章,我就帶大家一步步地,用<dialog>來構建一個功能完善、可以直接拿到項目里用的Modal組件。


HTML骨架

我們不再需要一堆div來模擬結構。HTML的骨架非常簡單清晰。

<button class="open-button">打開彈窗</button>
<dialog class="my-modal">
  <header class="modal-header">
    <h2>我是彈窗標題</h2>
    <button class="close-button">×</button>
  </header>
  <div class="modal-body">
    <p>這里是彈窗的主體內容。</p>
    <p>你可以試試按 Tab 鍵,焦點是不會跑到彈窗外面的。也可以按 Esc 鍵關閉。</p>
  </div>
  <footer class="modal-footer">
    <button class="confirm-button">確認</button>
  </footer>
</dialog>

這個結構里,headerbodyfooter只是為了樣式清晰,核心就是那個<dialog>標簽。


核心功能 - 用JS喚醒

我們需要一個簡單的腳本來控制dialog的開關。我們可以把它封裝成一個簡單的類,方便復用。

class Modal {
  constructor(dialogEl) {
    if (!dialogEl || dialogEl.tagName !== 'DIALOG') {
      console.error('需要一個 <dialog> 元素');
      return;
    }
    this.dialog = dialogEl;
    this.closeButton = this.dialog.querySelector('.close-button');
    
    // 把事件監(jiān)聽的this綁定到當前實例
    this.handleBackdropClick = this.handleBackdropClick.bind(this);
    
    this.init();
  }
  init() {
    this.closeButton?.addEventListener('click', () => this.close());
    this.dialog.addEventListener('click', this.handleBackdropClick);
  }
  open() {
    this.dialog.showModal();
  }
  close() {
    this.dialog.close();
  }
  // 實現(xiàn)點擊遮罩層關閉
  handleBackdropClick(event) {
    // getBoundingClientRect()可以獲取元素的大小和位置
    const rect = this.dialog.getBoundingClientRect();
    const isInDialog = (
      rect.top <= event.clientY && event.clientY <= rect.top + rect.height &&
      rect.left <= event.clientX && event.clientX <= rect.left + rect.width
    );
    if (!isInDialog) {
      this.close();
    }
  }
}
// 如何使用
const dialogEl = document.querySelector('.my-modal');
const openBtn = document.querySelector('.open-button');
const modal = new Modal(dialogEl);
openBtn.addEventListener('click', () => modal.open());

代碼解析:

  1. dialog.showModal() : 這是關鍵。調用它,瀏覽器會自動處理:

    • dialog放到頁面的最頂層(top layer),z-index再高也蓋不住它。
    • 顯示一個默認的遮罩層。
    • 自動管理焦點,并將頁面背景“惰性化”。
  2. dialog.close() : 關閉彈窗。

  3. 點擊遮罩層關閉:這是原生<dialog>默認不帶的功能,但實現(xiàn)起來很簡單。我們監(jiān)聽dialog本身的點擊事件,判斷點擊坐標是否在dialog的矩形區(qū)域內,如果不在,就說明點的是遮罩層,此時調用close()方法即可。


美化外觀

現(xiàn)在彈窗能工作了,但樣子還很丑。我們需要給它和它的遮罩層加點樣式。

.my-modal {
  width: min(90vw, 500px); /* 寬度最大500px,但不超過視口寬度的90% */
  border: none;
  border-radius: 8px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.2);
  padding: 0; /* 我們用內部元素來控制padding */
}
.modal-header, .modal-body, .modal-footer {
  padding: 1rem 1.5rem;
}
.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid #eee;
}
.close-button {
  background: none;
  border: none;
  font-size: 1.5rem;
  cursor: pointer;
}
/* 關鍵:用::backdrop偽元素,來定義遮罩層的樣式 */
.my-modal::backdrop {
  background-color: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(3px);
}

::backdrop 這個偽元素所有關于遮罩層的樣式,都應該寫在這里。


增加動畫 - 讓體驗更絲滑一些

默認的dialog是瞬間出現(xiàn)和消失的,體驗有點生硬。我們可以加點動畫。

.my-modal {
  /* ...其他樣式 */
  transition: opacity 0.3s, transform 0.3s;
}
/* 默認關閉狀態(tài),可以把它藏起來 */
.my-modal:not([open]) {
  opacity: 0;
  transform: translateY(30px);
}
.my-modal::backdrop {
  /* ...其他樣式 */
  transition: backdrop-filter 0.3s, background-color 0.3s;
}
.my-modal:not([open])::backdrop {
  backdrop-filter: blur(0);
  background-color: rgba(0, 0, 0, 0);
}

不過,你會發(fā)現(xiàn)關閉動畫不會生效,因為dialog.close()會立刻讓元素從DOM中消失。要實現(xiàn)完美的關閉動畫,需要一個小技巧:

// 在Modal類里,改造一下close方法
close() {
  this.dialog.classList.add('is-closing');
  this.dialog.addEventListener('animationend', () => {
    this.dialog.classList.remove('is-closing');
    this.dialog.close();
  }, { once: true });
}
@keyframes slide-out {
  from { opacity: 1; transform: translateY(0); }
  to { opacity: 0; transform: translateY(30px); }
}
.my-modal.is-closing {
  animation: slide-out 0.3s ease-out forwards;
}

這個方法稍微復雜一點,但能實現(xiàn)完美的關閉動畫。對于大部分簡單場景,沒有關閉動畫也是可以接受的。


最后我們看看兼容性:

到目前位置,主流瀏覽器幾乎都支持原生dialog,但是值得注意的是 Safari, 它的支持度比起它瀏覽器稍晚,2022年后才開始支持,對于 Safari 瀏覽器 我更推薦大家使用等價的 polyfill 去解決。(推薦使用 Chrome 官方的 dialog-polyfill)

?

分享完畢,謝謝大家??

轉自https://juejin.cn/post/7532302427423817780


該文章在 2025/8/5 9:55:44 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業(yè)務管理,結合碼頭的業(yè)務特點,圍繞調度、堆場作業(yè)而開發(fā)的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統(tǒng),標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved