DOM events
You can listen to any DOM event on an element (such as click or pointermove) with the on:
directive:
<script>
let m = { x: 0, y: 0 };
function handleMove(event) {
m.x = event.clientX;
m.y = event.clientY;
}
</script>
<div on:pointermove={handleMove}>
The pointer is at {m.x} x {m.y}
</div>
<style>
div {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
padding: 1rem;
}
</style>
You can also declare event handlers inline:
<script>
let m = { x: 0, y: 0 };
</script>
<div
on:pointermove={(e) => {
m = { x: e.clientX, y: e.clientY };
}}
>
The pointer is at {m.x} x {m.y}
</div>
<style>
div {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
padding: 1rem;
}
</style>
In some frameworks you may see recommendations to avoid inline event handlers for performance reasons, particularly inside loops. That advice doesn't apply to Svelte — the compiler will always do the right thing, whichever form you choose.
Event modifiers
DOM event handlers can have modifiers that alter their behaviour. For example, a handler with a once modifier will only run a single time:
<button on:click|once={() => alert('clicked')}>
Click me
</button>
Event modifiers | Meaning |
---|---|
preventDefault |
calls event.preventDefault() before running the handler |
stopPropagation |
calls event.stopPropagation() , preventing the event reaching the next element |
passive |
improves scrolling performance on touch/wheel events (Svelte will add it automatically where it's safe to do so) |
nonpassive |
explicitly set passive: false
|
capture |
fires the handler during the capture phase instead of the bubbling phase |
once |
remove the handler after the first time it runs |
self |
only trigger handler if event.target is the element itself |
trusted |
only trigger handler if event.isTrusted is true , meaning the event was triggered by a user action rather than because some JavaScript called element.dispatchEvent(...)
|
You can chain modifiers together, e.g. on:click|once|capture={...}
.
Event: isTrusted
property
The isTrusted
read-only property of the Event
interface is a boolean value that is true
when the event was generated by a user action, and false
when the event was created or modified by a script or dispatched via EventTarget.dispatchEvent()
.
Component events
Components can also dispatch events. To do so, they must create an event dispatcher.
Inner.svelte
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
function sayHello() {
dispatch('message', {
text: 'Hello!'
});
}
</script>
<button on:click={sayHello}>
Click to say hello
</button>
Note that createEventDispatcher
must be called when the component is first instantiated — you can't do it later inside.
Then, add an on:message
handler in App.svelte
:
App.svelte
<script>
import Inner from './Inner.svelte';
function handleMessage(event) {
alert(event.detail.text);
}
</script>
<Inner on:message={handleMessage} />
Event forwarding 事件转发
Unlike DOM events, component events don't bubble. If you want to listen to an event on some deeply nested component, the intermediate components must forward the event.
Inner.svelte
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
function sayHello() {
dispatch('message', {
text: 'Hello!'
});
}
</script>
<button on:click={sayHello}>
Click to say hello
</button>
Outer.svelte
<script>
import Inner from './Inner.svelte';
</script>
<Inner on:message />
App.svelte
<script>
import Outer from './Outer.svelte';
function handleMessage(event) {
alert(event.detail.text);
}
</script>
<Outer on:message={handleMessage} />
DOM Event forwarding
Event forwarding works for DOM events too.
BigRedButton.svelte
<button on:click>
Push
</button>
App.svelte
<script>
import BigRedButton from './BigRedButton.svelte';
import horn from './horn.mp3';
const audio = new Audio();
audio.src = horn;
function handleClick() {
audio.play();
}
</script>
<BigRedButton on:click={handleClick} />