Passing a callback is the most straightforward. Light. Simple. In most cases, a callback can do, and IMO they're preferable.
You can pass only one callback, though, whereas you can have multiple listeners on the same event.
<script>
import { onMount } from 'svelte'
import Beeper from './Beeper.svelte'
let beeper
onMount(() => {
const disposes = [
beeper.$on('beep', () => console.log('dynamic A')),
beeper.$on('beep', () => console.log('dynamic B'))
]
return () => disposes.forEach(fn => fn())
})
</script>
<Beeper on:beep={() => console.log('inline')} bind:this={beeper} />
Perhaps more interesting with standalone components?
const beeper = new Beeper({ target: document.body })
beeper.$on('beep', ...)
beeper.$on('beep', ...)
Events can also be easier to proxy:
Proxy.svelte
<script>
import Beeper from './Beeper.svelte'
</script>
<Beeper on:beep />
App.svelte
<script>
import Proxy from './Proxy.svelte'
</script>
<Proxy on:beep={() => console.log('beep')} />
On the other hand, events can be a bother to proxy:
Proxy.svelte
<script>
import Beeper from './Beeper.svelte'
</script>
<!-- callbacks are all in the $$props bag, but I have to know every
event that I want to proxy -->
<Beeper {...$$props} on:beep />
And they're even only arguably easier to proxy:
<script>
import Beeper from './Beeper.svelte'
export let onBeep
</script>
<Beeper {onBeep} />
Also, I'm not sure you can have callbacks with the custom element flavor of Svelte, so you're possibly stuck with events there.
There are also situations where you might prefer the event API for consistence (especially when your component closely mimic an existing DOM element), elegance or aesthetic reasons.
Personally, I generally just go with callbacks unless a callbacks won't do. That's pretty infrequent.
Ah! And no, you can't have events on a slot. But you can't really have a callback either, can you?
<slot onBeep={onBeep} />
This would make the onBeep
function available as let:onBeep
in a consumer component:
<SlotBeeper let:onBeep>
{@debug onBeep}
<AnotherCmp {onBeep} />
</SlotBeeper>