「我將在今天向你提出一個莫大的請求,」他一邊說一邊心滿意足的用
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