「我將在今天向你提出一個莫大的請求,」他一邊說一邊心滿意足的用
modifier修飾手邊的事件。「所以我希望你能夠真正認識我。我不希望你會認為我只是一個路人。你看,我總是將自己投向陌生人群,東飄西盪,為的只是讓我能夠忘記那些傷心事。」~節錄自《The Great Svelte:第四章》
<dialog> 元素昨天我們又掌握了更多在 Svelte 這個架構中傳遞事件的方法,今天繼續來討論事件。除了事件的傳遞之外,在某些特殊的狀況,我們反而可能希望事件不要傳遞,或是想要避免預設事件被觸發,或是希望事件只會觸發一次,等等不同的無理取鬧的要求。Svelte 想當然爾必須要配合這些任性的要求。但,究竟該怎麼做到呢?
  答案是透過事件修飾。在 Svelte 的架構中,我們用 on:eventName 來表示我們要接收選定的事件。用 ={eventHandler} 來設定事件處理器。用 |modifier 來對事件進行控制,或是對事件處理器的使用時機加上條件。完整的寫法是像這樣:
<element on:eventName|modifier={eventHandler} />
  修飾事件,就是指透過這個 modifier,來達成我們各種不尋常的要求:
preventDefault
  利用這個修飾詞,表示事件發生時,會先呼叫 event.preventDefault(),接著才由事件處理器進行處理。當我們在實作使用者介面的表格時,很實用的一個功能。
stopPropagation
  利用這個修飾詞來呼叫 event.stopPropagation,避免事件繼續往上傳遞到其他 HTML 元素。
once
  利用這個修飾詞,限制事件處理器只能運作一次。當事件被接收並透過事件處理器處理完成後,該事件處理器就會被移除。
self
  利用這個修飾詞,限制事件處理器只會處理發生自本身 HTML 元素的事件,也就是 event.target 必須是本身那個 HTML 元素,事件處理器才會進行處理。
trusted
  利用這個修飾詞,限制事件處理器只會處理透過使用者介面觸發的事件,而忽略那些用 Javascript 呼叫 dispatchEvent() 做出來的「虛擬」事件。也就是說只會處理 event.isTrusted 為 true 的事件。
當然如果想要的話,我們也可以在事件處理器上加入多個不同的修飾詞:
<element on:eventName|modifierA|modifier|…={eventHandler} />
了解了事件修飾的用法跟語法之後,就讓我們在專案當中一邊實作一個互動視窗 (Modal),一邊練習使用事件修飾看看吧。
<dialog> 元素  我們可以快速的利用 HTML 的 <dialog> 元素以及它所提供的功能快速做出一個互動視窗 (Modal)。一個互動視窗 (Modal) 最重要的就是兩個功能,【開啟】跟【關閉】。當互動視窗 (Modal)【開啟】時,使用者介面當中其他元素的功能都會被無效化,有點像是強迫使用者將注意力集中在眼前的互動視窗 (Modal) 的意思。建議的互動視窗 (Modal) 【開啟】方式,是透過 Javascript:
dialog.showModal();
而要【關閉】互動視窗 (Modal),則可以透過按下 【Esc】鍵,或同樣透過 Javascript:
dialog.close();
  那麼讓我們在專案中加入一個互動視窗 (Modal) 看看吧。就像先前在第 06 天提過的,為了讓檔案分工清楚,我們也另外做出一個專屬於互動視窗的 Svelte 元件 Modal.svelte吧:
/src/lib/Modal.svelte
<script>
  let dialog;
  
  setTimeout(() => {
    dialog = document.querySelector('dialog');
    dialog.showModal();
  }, 1);
</script>
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-noninteractive-element-interactions -->
<dialog>
  <!-- svelte-ignore a11y-no-static-element-interactions -->
  <div>
    <div class="title">
      <h2>Forbidden</h2>
      <small><em>adjective</em> for·bid·den \fər-ˈbi-dᵊn \</small>
    </div>
    <hr />
    <div class="content">
      <p>
        You have no privilidge to enter domain beyond 87. Please register
        as member so we can sent you some spam email.
      </p>
    </div>
    <hr />
    <!-- svelte-ignore a11y-autofocus -->
    <div class="footer">
      <button autofocus>close modal</button>
    </div>
  </div>
</dialog>
第二行:let dialog; 
  先宣告一個 dialog 變數,之後用來表示 HTML 的 <dialog> 元素。
第五行:dialog = document.querySelector('dialog');
  用 document.querySelector('dialog') 將 HTML 的 <dialog> 元素用 Javascript 變數 dialog 來表示。注意到我們將這個動作利用 setTimeout() 設定在 Javascript 開始執行的 1 毫秒之後,原因是在 Svelte 當中,Javascript 開始執行時,我們的 HTML 元素還沒掛載好 。在之後的文章中,會介紹方法將這個看起來很彆扭的程式碼改寫得更乾淨。
第六行:dialog.showModal();
  一拿到 <dialog> 這個元素,我們就用 showModal() 這個函式來開啟互動視窗 (Modal)。
第十二行:<dialog>
  就是我們用來實作出的互動視窗的 <dialog> 本人。

圖一、從互動視窗大聲呼喊「Forbidden」!
今天關於事件修飾的初步介紹就到這邊了,我們明白事件修飾的語法,也知道怎麼在 Svelte 當中簡單做出一個互動視窗 (Modal)。但我們還沒真正讓互動視窗 (Modal) 動起來呢?沒關係,今天是中秋節,先祝大家月圓人團圓。剩下的內容就明天分曉囉。謝謝大家。
  完整的 Modal.svelte,包含 CSS 設定:
/src/lib/Modal.svelte
<script>
  let dialog;
  
  setTimeout(() => {
    dialog = document.querySelector('dialog');
    dialog.showModal();
  }, 1);
</script>
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-noninteractive-element-interactions -->
<dialog>
  <!-- svelte-ignore a11y-no-static-element-interactions -->
  <div>
    <div class="title">
      <h2>Forbidden</h2>
      <small><em>adjective</em> for·bid·den \fər-ˈbi-dᵊn \</small>
    </div>
    <hr />
    <div class="content">
      <p>
        You have no privilidge to enter domain beyond 87. Please register
        as member so we can sent you some spam email.
      </p>
    </div>
    <hr />
    <!-- svelte-ignore a11y-autofocus -->
    <div class="footer">
      <button autofocus>close modal</button>
    </div>
  </div>
</dialog>
<style>
  dialog {
    color: var(--color-text);
    max-width: 20em;
    border-radius: 0.2em;
    border: none;
    padding: 2em;
    margin: auto;
    box-shadow: 0.5em 0.5em 1.5em rgba(0, 0, 0, 0.1),
      -0.5em -0.5em 1.5em rgba(0, 0, 0, 0.1);
  }
  dialog::backdrop {
    background: rgba(0, 0, 0, 0.4);
  }
  dialog > div > div {
    margin: 1em 0;
  }
  button {
    font-size: 1.1em;
    padding: 0.5em;
    border-radius: 0.2em;
    border: none;
    outline: none;
    cursor: pointer;
  }
  button:hover {
  filter: brightness(1.02);
  }
</style>
此時的檔案架構:
C:.
│   .gitignore
│   index.html
│   jsconfig.json
│   package-lock.json
│   package.json
│   README.md
│   svelte.config.js
│   vite.config.js
│
├───.vscode
├───node_modules
├───public
│       vite.svg
│
└───src
    │   app.css
    │   App.svelte
    │   main.js
    │   vite-env.d.ts
    │
    ├───assets
    │       svelte.svg
    │
    └───lib
            Counter.svelte
            Modal.svelte