跳至主要內容 跳至文件導覽

互動視窗(Modal)

使用 Bootstrap 的 JavaScript 互動視窗外掛程式,為您的網站加入燈箱效果、使用者通知或完全自訂的對話框內容。

運作原理(How it works)

在開始使用 Bootstrap 的互動視窗元件之前,請務必閱讀以下內容,因為我們的選單選項最近有所變更。

  • 互動視窗是使用 HTML、CSS 和 JavaScript 建構的。它們定位於文件中所有其他元素之上,並移除 <body> 的捲動,讓互動視窗內容可以捲動。
  • 點擊互動視窗的「背景幕」將自動關閉互動視窗。
  • Bootstrap 一次只支援一個互動視窗。不支援巢狀互動視窗,因為我們認為這會造成不良的使用者體驗。
  • 互動視窗使用 position: fixed,這有時在渲染上會有些問題。盡可能將您的互動視窗 HTML 放在頂層位置,以避免其他元素的潛在干擾。當在另一個固定元素中巢狀 .modal 時,您可能會遇到問題。
  • 再次強調,由於 position: fixed 的關係,在行動裝置上使用互動視窗有一些注意事項。請參閱我們的瀏覽器支援文件了解詳情。
  • 由於 HTML5 定義其語意的方式,autofocus HTML 屬性在 Bootstrap 互動視窗中沒有效果。若要達到相同的效果,請使用一些自訂 JavaScript:
const myModal = document.getElementById('myModal')
const myInput = document.getElementById('myInput')

myModal.addEventListener('shown.bs.modal', () => {
  myInput.focus()
})

此元件的動畫效果取決於 prefers-reduced-motion 媒體查詢。請參閱我們無障礙文件中的減少動態效果章節

繼續閱讀以獲取展示和使用指南。

範例(Examples)

以下是一個_靜態_互動視窗範例(意味著其 positiondisplay 已被覆寫)。包含互動視窗標題、互動視窗內容(padding 所需)和互動視窗頁尾(選用)。我們建議您盡可能在互動視窗標題中包含關閉動作,或提供另一個明確的關閉動作。

<div class="modal" tabindex="-1">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Modal title</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <p>Modal body text goes here.</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

在上面的靜態範例中,我們使用 <h5> 來避免文件頁面中的標題層級問題。然而,在結構上,互動視窗對話框代表其自己獨立的文件/情境,因此 .modal-title 理想上應該是 <h1>。如有需要,您可以使用字型大小通用類別來控制標題的外觀。以下所有即時範例都使用這種方法。

即時展示(Live demo)

點擊下方按鈕切換互動視窗展示。它將從頁面頂部向下滑入並淡入。

<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">
  Launch demo modal
</button>

<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

靜態背景幕(Static backdrop)

當背景幕設定為靜態時,點擊互動視窗外部不會關閉它。點擊下方按鈕試試看。

<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#staticBackdrop">
  Launch static backdrop modal
</button>

<!-- Modal -->
<div class="modal fade" id="staticBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="staticBackdropLabel">Modal title</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Understood</button>
      </div>
    </div>
  </div>
</div>

捲動長內容(Scrolling long content)

當互動視窗對於使用者的視窗或裝置來說太長時,它們會獨立於頁面本身進行捲動。試試下面的展示來看看我們的意思。

您也可以透過在 .modal-dialog 上加入 .modal-dialog-scrollable 來建立可捲動的互動視窗,允許捲動互動視窗內容。

<!-- Scrollable modal -->
<div class="modal-dialog modal-dialog-scrollable">
  ...
</div>

垂直置中(Vertically centered)

.modal-dialog 上加入 .modal-dialog-centered 來將互動視窗垂直置中。

<!-- Vertically centered modal -->
<div class="modal-dialog modal-dialog-centered">
  ...
</div>

<!-- Vertically centered scrollable modal -->
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable">
  ...
</div>

工具提示框與彈出提示框(Tooltips and popovers)

工具提示框彈出提示框可以根據需要放置在互動視窗中。當互動視窗關閉時,其中的任何工具提示框和彈出提示框也會自動關閉。

<div class="modal-body">
  <h2 class="fs-5">Popover in a modal</h2>
  <p>This <button class="btn btn-secondary" data-bs-toggle="popover" title="Popover title" data-bs-content="Popover body content is set in this attribute.">button</button> triggers a popover on click.</p>
  <hr>
  <h2 class="fs-5">Tooltips in a modal</h2>
  <p><a href="#" data-bs-toggle="tooltip" title="Tooltip">This link</a> and <a href="#" data-bs-toggle="tooltip" title="Tooltip">that link</a> have tooltips on hover.</p>
</div>

使用格線系統(Using the grid)

透過在 .modal-body 中巢狀 .container-fluid,在互動視窗中使用 Bootstrap 格線系統。然後,像在其他地方一樣使用一般的格線系統類別。

<div class="modal-body">
  <div class="container-fluid">
    <div class="row">
      <div class="col-md-4">.col-md-4</div>
      <div class="col-md-4 ms-auto">.col-md-4 .ms-auto</div>
    </div>
    <div class="row">
      <div class="col-md-3 ms-auto">.col-md-3 .ms-auto</div>
      <div class="col-md-2 ms-auto">.col-md-2 .ms-auto</div>
    </div>
    <div class="row">
      <div class="col-md-6 ms-auto">.col-md-6 .ms-auto</div>
    </div>
    <div class="row">
      <div class="col-sm-9">
        Level 1: .col-sm-9
        <div class="row">
          <div class="col-8 col-sm-6">
            Level 2: .col-8 .col-sm-6
          </div>
          <div class="col-4 col-sm-6">
            Level 2: .col-4 .col-sm-6
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

變化的互動視窗內容(Varying modal content)

有一堆按鈕都會觸發相同的互動視窗,但內容略有不同?使用 event.relatedTargetHTML data-bs-* 屬性,根據點擊的按鈕來變更互動視窗的內容。

以下是即時展示,後面是範例 HTML 和 JavaScript。更多資訊請閱讀互動視窗事件文件以了解 relatedTarget 的詳細內容。

html
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@mdo">Open modal for @mdo</button>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@fat">Open modal for @fat</button>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@getbootstrap">Open modal for @getbootstrap</button>

<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalLabel">New message</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <form>
          <div class="mb-3">
            <label for="recipient-name" class="col-form-label">Recipient:</label>
            <input type="text" class="form-control" id="recipient-name">
          </div>
          <div class="mb-3">
            <label for="message-text" class="col-form-label">Message:</label>
            <textarea class="form-control" id="message-text"></textarea>
          </div>
        </form>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Send message</button>
      </div>
    </div>
  </div>
</div>
const exampleModal = document.getElementById('exampleModal')
if (exampleModal) {
  exampleModal.addEventListener('show.bs.modal', event => {
    // Button that triggered the modal
    const button = event.relatedTarget
    // Extract info from data-bs-* attributes
    const recipient = button.getAttribute('data-bs-whatever')
    // If necessary, you could initiate an Ajax request here
    // and then do the updating in a callback.

    // Update the modal's content.
    const modalTitle = exampleModal.querySelector('.modal-title')
    const modalBodyInput = exampleModal.querySelector('.modal-body input')

    modalTitle.textContent = `New message to ${recipient}`
    modalBodyInput.value = recipient
  })
}

在互動視窗之間切換(Toggle between modals)

透過巧妙地放置 data-bs-targetdata-bs-toggle 屬性,在多個互動視窗之間切換。例如,您可以在已開啟的登入互動視窗中切換到密碼重設互動視窗。請注意,多個互動視窗不能同時開啟—這個方法只是在兩個獨立的互動視窗之間切換。

html
<div class="modal fade" id="exampleModalToggle" aria-hidden="true" aria-labelledby="exampleModalToggleLabel" tabindex="-1">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalToggleLabel">Modal 1</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        Show a second modal and hide this one with the button below.
      </div>
      <div class="modal-footer">
        <button class="btn btn-primary" data-bs-target="#exampleModalToggle2" data-bs-toggle="modal">Open second modal</button>
      </div>
    </div>
  </div>
</div>
<div class="modal fade" id="exampleModalToggle2" aria-hidden="true" aria-labelledby="exampleModalToggleLabel2" tabindex="-1">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalToggleLabel2">Modal 2</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        Hide this modal and show the first with the button below.
      </div>
      <div class="modal-footer">
        <button class="btn btn-primary" data-bs-target="#exampleModalToggle" data-bs-toggle="modal">Back to first</button>
      </div>
    </div>
  </div>
</div>
<button class="btn btn-primary" data-bs-target="#exampleModalToggle" data-bs-toggle="modal">Open first modal</button>

變更動畫(Change animation)

$modal-fade-transform 變數決定互動視窗淡入動畫之前 .modal-dialog 的變形狀態,$modal-show-transform 變數決定互動視窗淡入動畫結束時 .modal-dialog 的變形。

例如,如果您想要縮放動畫,可以設定 $modal-fade-transform: scale(.8)

移除動畫(Remove animation)

對於只是單純出現而非淡入檢視的互動視窗,請從互動視窗標記中移除 .fade 類別。

<div class="modal" tabindex="-1" aria-labelledby="..." aria-hidden="true">
  ...
</div>

動態高度(Dynamic heights)

如果互動視窗在開啟時高度發生變化,您應該呼叫 myModal.handleUpdate() 來重新調整互動視窗的位置,以防出現捲軸。

無障礙(Accessibility)

請務必在 .modal 上加入 aria-labelledby="...",參考互動視窗標題。此外,您可以在 .modal 上使用 aria-describedby 來提供互動視窗對話框的描述。請注意,您不需要加入 role="dialog",因為我們已經透過 JavaScript 加入它了。

嵌入 YouTube 影片(Embedding YouTube videos)

在互動視窗中嵌入 YouTube 影片需要額外的 JavaScript(不在 Bootstrap 中),以自動停止播放等功能。請參閱這篇有用的 Stack Overflow 文章了解更多資訊。

可選尺寸(Optional sizes)

互動視窗有三種可選尺寸,可透過放置在 .modal-dialog 上的修飾類別來使用。這些尺寸在特定中斷點啟用,以避免在較窄的視窗中出現水平捲軸。

尺寸類別互動視窗最大寬度
小型.modal-sm300px
預設500px
大型.modal-lg800px
特大型.modal-xl1140px

我們沒有修飾類別的預設互動視窗構成「中型」尺寸的互動視窗。

<div class="modal-dialog modal-xl">...</div>
<div class="modal-dialog modal-lg">...</div>
<div class="modal-dialog modal-sm">...</div>

全螢幕互動視窗(Fullscreen Modal)

另一個覆寫選項是彈出覆蓋使用者視窗的互動視窗,可透過放置在 .modal-dialog 上的修飾類別來使用。

類別適用範圍
.modal-fullscreen始終
.modal-fullscreen-sm-down576px
.modal-fullscreen-md-down768px
.modal-fullscreen-lg-down992px
.modal-fullscreen-xl-down1200px
.modal-fullscreen-xxl-down1400px
<!-- Full screen modal -->
<div class="modal-dialog modal-fullscreen-sm-down">
  ...
</div>

CSS

變數(Variables)

Added in v5.2.0

作為 Bootstrap 不斷發展的 CSS 變數方法的一部分,互動視窗現在在 .modal.modal-backdrop 上使用區域 CSS 變數來增強即時自訂功能。CSS 變數的值是透過 Sass 設定的,因此仍然支援 Sass 自訂。

--#{$prefix}modal-zindex: #{$zindex-modal};
--#{$prefix}modal-width: #{$modal-md};
--#{$prefix}modal-padding: #{$modal-inner-padding};
--#{$prefix}modal-margin: #{$modal-dialog-margin};
--#{$prefix}modal-color: #{$modal-content-color};
--#{$prefix}modal-bg: #{$modal-content-bg};
--#{$prefix}modal-border-color: #{$modal-content-border-color};
--#{$prefix}modal-border-width: #{$modal-content-border-width};
--#{$prefix}modal-border-radius: #{$modal-content-border-radius};
--#{$prefix}modal-box-shadow: #{$modal-content-box-shadow-xs};
--#{$prefix}modal-inner-border-radius: #{$modal-content-inner-border-radius};
--#{$prefix}modal-header-padding-x: #{$modal-header-padding-x};
--#{$prefix}modal-header-padding-y: #{$modal-header-padding-y};
--#{$prefix}modal-header-padding: #{$modal-header-padding}; // Todo in v6: Split this padding into x and y
--#{$prefix}modal-header-border-color: #{$modal-header-border-color};
--#{$prefix}modal-header-border-width: #{$modal-header-border-width};
--#{$prefix}modal-title-line-height: #{$modal-title-line-height};
--#{$prefix}modal-footer-gap: #{$modal-footer-margin-between};
--#{$prefix}modal-footer-bg: #{$modal-footer-bg};
--#{$prefix}modal-footer-border-color: #{$modal-footer-border-color};
--#{$prefix}modal-footer-border-width: #{$modal-footer-border-width};
--#{$prefix}backdrop-zindex: #{$zindex-modal-backdrop};
--#{$prefix}backdrop-bg: #{$modal-backdrop-bg};
--#{$prefix}backdrop-opacity: #{$modal-backdrop-opacity};

Sass 變數(Sass variables)

$modal-inner-padding:               $spacer;

$modal-footer-margin-between:       .5rem;

$modal-dialog-margin:               .5rem;
$modal-dialog-margin-y-sm-up:       1.75rem;

$modal-title-line-height:           $line-height-base;

$modal-content-color:               var(--#{$prefix}body-color);
$modal-content-bg:                  var(--#{$prefix}body-bg);
$modal-content-border-color:        var(--#{$prefix}border-color-translucent);
$modal-content-border-width:        var(--#{$prefix}border-width);
$modal-content-border-radius:       var(--#{$prefix}border-radius-lg);
$modal-content-inner-border-radius: subtract($modal-content-border-radius, $modal-content-border-width);
$modal-content-box-shadow-xs:       var(--#{$prefix}box-shadow-sm);
$modal-content-box-shadow-sm-up:    var(--#{$prefix}box-shadow);

$modal-backdrop-bg:                 $black;
$modal-backdrop-opacity:            .5;

$modal-header-border-color:         var(--#{$prefix}border-color);
$modal-header-border-width:         $modal-content-border-width;
$modal-header-padding-y:            $modal-inner-padding;
$modal-header-padding-x:            $modal-inner-padding;
$modal-header-padding:              $modal-header-padding-y $modal-header-padding-x; // Keep this for backwards compatibility

$modal-footer-bg:                   null;
$modal-footer-border-color:         $modal-header-border-color;
$modal-footer-border-width:         $modal-header-border-width;

$modal-sm:                          300px;
$modal-md:                          500px;
$modal-lg:                          800px;
$modal-xl:                          1140px;

$modal-fade-transform:              translate(0, -50px);
$modal-show-transform:              none;
$modal-transition:                  transform .3s ease-out;
$modal-scale-transform:             scale(1.02);

Sass 迴圈(Sass loops)

響應式全螢幕互動視窗是透過 $breakpoints 映射和 scss/_modal.scss 中的迴圈產生的。

@each $breakpoint in map-keys($grid-breakpoints) {
  $infix: breakpoint-infix($breakpoint, $grid-breakpoints);
  $postfix: if($infix != "", $infix + "-down", "");

  @include media-breakpoint-down($breakpoint) {
    .modal-fullscreen#{$postfix} {
      width: 100vw;
      max-width: none;
      height: 100%;
      margin: 0;

      .modal-content {
        height: 100%;
        border: 0;
        @include border-radius(0);
      }

      .modal-header,
      .modal-footer {
        @include border-radius(0);
      }

      .modal-body {
        overflow-y: auto;
      }
    }
  }
}

使用方式(Usage)

互動視窗外掛程式透過 data 屬性或 JavaScript 按需切換您的隱藏內容。它還會覆寫預設的捲動行為,並產生 .modal-backdrop 來提供點擊區域,以便在點擊互動視窗外部時關閉顯示的互動視窗。

透過 data 屬性(Via data attributes)

切換(Toggle)

無需編寫 JavaScript 即可啟動互動視窗。在控制元素(如按鈕)上設定 data-bs-toggle="modal",並加上 data-bs-target="#foo"href="#foo" 來指定要切換的特定互動視窗。

<button type="button" data-bs-toggle="modal" data-bs-target="#myModal">Launch modal</button>

關閉(Dismiss)

可以透過 modal 內部按鈕上的 data-bs-dismiss 屬性來實現關閉功能,如下所示:

<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>

或者透過 modal 外部的按鈕,使用額外的 data-bs-target,如下所示:

<button type="button" class="btn-close" data-bs-dismiss="modal" data-bs-target="#my-modal" aria-label="Close"></button>

雖然兩種關閉互動視窗的方式都受支援,但請注意,從互動視窗外部關閉不符合 ARIA 編寫實踐指南的對話框(互動視窗)模式。請自行承擔風險。

透過 JavaScript(Via JavaScript)

使用一行 JavaScript 建立互動視窗:

const myModal = new bootstrap.Modal(document.getElementById('myModal'), options)
// or
const myModalAlternative = new bootstrap.Modal('#myModal', options)

選項(Options)

由於選項可以透過 data 屬性或 JavaScript 傳遞,您可以將選項名稱附加到 data-bs-,例如 data-bs-animation="{value}"。透過 data 屬性傳遞選項時,請確保將選項名稱的大小寫類型從「camelCase」更改為「kebab-case」。例如,使用 data-bs-custom-class="beautifier" 而不是 data-bs-customClass="beautifier"

從 Bootstrap 5.2.0 開始,所有元件都支援實驗性的保留 data 屬性 data-bs-config,可以將簡單的元件配置作為 JSON 字串存放。當元素同時具有 data-bs-config='{"delay":0, "title":123}'data-bs-title="456" 屬性時,最終的 title 值將是 456,個別的 data 屬性將覆寫 data-bs-config 中給定的值。此外,現有的 data 屬性也能夠存放 JSON 值,例如 data-bs-delay='{"show":0,"hide":150}'

最終的配置物件是 data-bs-configdata-bs-js object 的合併結果,其中最後給定的鍵值對會覆寫其他的。

名稱類型預設值說明
backdropboolean, 'static'true包含互動視窗背景幕元素。或者,指定 static 以建立點擊時不會關閉互動視窗的背景幕。
focusbooleantrue初始化時將焦點放在互動視窗上。
keyboardbooleantrue按下 Escape 鍵時關閉互動視窗。

方法(Methods)

所有 API 方法都是非同步的,並會啟動一個過渡效果。 它們會在過渡開始後立即回傳給呼叫者,但在過渡結束之前。此外,對正在過渡中的元件進行方法呼叫將被忽略。在我們的 JavaScript 文件中了解更多。

傳遞選項(Passing options)

將您的內容啟動為互動視窗。接受可選的選項 object

const myModal = new bootstrap.Modal('#myModal', {
  keyboard: false
})
方法說明
dispose銷毀元素的互動視窗。(移除儲存在 DOM 元素上的資料)
getInstance_靜態_方法,允許您取得與 DOM 元素關聯的互動視窗實體。
getOrCreateInstance_靜態_方法,允許您取得與 DOM 元素關聯的互動視窗實體,如果尚未初始化則建立新的。
handleUpdate如果互動視窗在開啟時高度發生變化(例如出現捲軸),手動重新調整互動視窗的位置。
hide手動隱藏互動視窗。在互動視窗實際隱藏之前傳回給呼叫者(即在 hidden.bs.modal 事件發生之前)。
show手動開啟互動視窗。在互動視窗實際顯示之前傳回給呼叫者(即在 shown.bs.modal 事件發生之前)。此外,您可以傳遞一個 DOM 元素作為引數,可在互動視窗事件中接收(作為 relatedTarget 屬性)。(例如 const modalToggle = document.getElementById('toggleMyModal'); myModal.show(modalToggle))。
toggle手動切換互動視窗。在互動視窗實際顯示或隱藏之前傳回給呼叫者(即在 shown.bs.modalhidden.bs.modal 事件發生之前)。

事件(Events)

Bootstrap 的互動視窗類別公開了一些事件,用於掛接互動視窗功能。所有互動視窗事件都在互動視窗本身觸發(即在 <div class="modal"> 上)。

事件說明
hide.bs.modal當呼叫 hide 實體方法時立即觸發此事件。可以透過呼叫 event.preventDefault() 來阻止。請參閱 JavaScript 事件文件了解更多關於事件阻止的詳細資訊。
hidden.bs.modal當互動視窗對使用者隱藏完成時觸發此事件(會等待 CSS 轉場效果完成)。
hidePrevented.bs.modal當互動視窗顯示、其背景幕為 static 且點擊互動視窗外部時觸發此事件。當按下 Escape 鍵且 keyboard 選項設定為 false 時也會觸發此事件。
show.bs.modal當呼叫 show 實體方法時立即觸發此事件。如果是由點擊引起的,被點擊的元素可作為事件的 relatedTarget 屬性取得。
shown.bs.modal當互動視窗對使用者顯示完成時觸發此事件(會等待 CSS 轉場效果完成)。如果是由點擊引起的,被點擊的元素可作為事件的 relatedTarget 屬性取得。
const myModalEl = document.getElementById('myModal')
myModalEl.addEventListener('hidden.bs.modal', event => {
  // do something...
})