3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SvelteAdvent Calendar 2024

Day 14

Svelte5ではcreateEventDispatcher関数が非推奨になりました

Last updated at Posted at 2024-12-13

createEventDispatcherとは

createEventDispatcherは、Svelteコンポーネントからカスタムイベントをディスパッチ(発行)するための関数です。これを使うことで、子コンポーネントが親コンポーネントにデータやイベントを通知することができます。

Svelte5でどう変わったのか

Svelte5では、createEventDispatcher関数が非推奨となり、代わりにPropsとしてコールバック関数を渡すようになりました。

また、 on:ディレクティブが非推奨になっていますのでon:clickonclickのように単なるプロパティとしてイベントハンドラを指定するようになりました。

例をいくつか紹介します。

Docs

例1

Svelte4以前の書き方

[Demo]https://svelte.dev/playground/9553ad5a88c046c2a1d009e05894032c?version=4.2.19)

子コンポーネント
<script>
 import { createEventDispatcher } from 'svelte';
 
 const dispatch = createEventDispatcher();
</script>

<button on:click={() => dispatch('notify', 'detail value')}>Fire Event</button>
親コンポーネント
<script>
  import Child from './Child.svelte';

  function callbackFunction(event) {
    console.log(`Notify fired! Detail: ${event.detail}`);
  }
</script>

<Child on:notify={callbackFunction} />

Svelte5で変わった書き方

Demo

子コンポーネント
<script>
  let { onNotify } = $props();
</script>

<button onclick={() => onNotify('detail value')}>Fire Event</button>
親コンポーネント
<script>
  import Child from './Child.svelte';

  function handleNotify(detail) {
    console.log(`Notify fired! Detail: ${detail}`);
  }
</script>

<Child onNotify={handleNotify} />

例2

Svelte4以前の書き方

Demo

子コンポーネント
<script>
  import { createEventDispatcher } from 'svelte';
  const dispatch = createEventDispatcher();

  function handleAdd() {
    dispatch('add');
  }

  function handleSubtract() {
    dispatch('subtract');
  }
</script>

<button on:click={handleAdd}>Add</button>
<button on:click={handleSubtract}>Subtract</button>
親コンポーネント
<script>
  import Child from './Child.svelte';
  let number = 0;

  function handleAdd() {
    number++;
  }
  
  function handleSubtract() {
    number--;
  }
</script>

<Child on:add={handleAdd} on:subtract={handleSubtract} />

<p>Number: {number}</p>

Svelte5で変わった書き方

Demo

子コンポーネント
<script>
  let { add, subtract } = $props();
</script>

<button onclick={add}>Add</button>
<button onclick={subtract}>Subtract</button>
親コンポーネント
<script>
  import Child from "./Child.svelte"

  let number = $state(0);
</script>

<Child add={() => number++} subtract={() => number--} />

<p>Number: {number}</p>

例3

Svelte4以前の書き方

Demo

子コンポーネント
<script>
	import { createEventDispatcher } from 'svelte';
 
	const dispatch = createEventDispatcher();
 
	let power = 5;
</script>

<button on:click={() => dispatch('inflate', power)}>
	inflate
</button>

<button on:click={() => dispatch('deflate', power)}>
	deflate
</button>

<button on:click={() => power--}>-</button>

Pump power: {power}

<button on:click={() => power++}>+</button>
親コンポーネント
<script>
	import Child from './Child.svelte';

	let size = 15;
	let burst = false;

	function reset() {
		size = 15;
		burst = false;
	}
</script>

<Child
	on:inflate={(power) => {
		size += power.detail;
		if (size > 75) burst = true;
	}}
	on:deflate={(power) => {
		if (size > 0) size -= power.detail;
	}}
/>

{#if burst}
	<button on:click={reset}>new balloon</button>
	<span class="boom">💥</span>
{:else}
	<span class="balloon" style="scale: {0.01 * size}">
		🎈
	</span>
{/if}

<style>
	span {
		position: fixed;
		left: 0;
		top: 0;
		width: 100%;
		height: 100%;
		font-size: 100vh;
		text-align: center;
		line-height: 1;
		pointer-events: none;
	}

	.balloon {
		transition: scale 0.2s;
	}

	.boom {
		animation: boom 0.5s forwards;
	}

	@keyframes boom {
		0% {scale: 0.6}
		25% {scale: 0.75}
		100% {scale: 0}
	}
</style>

Svelte5で変わった書き方

Demo

子コンポーネント
<script>
	let { inflate, deflate } = $props();
	
	let power = $state(5);
</script>

<button onclick={() => inflate(power)}>
	inflate
</button>

<button onclick={() => deflate(power)}>
	deflate
</button>

<button onclick={() => power--}>-</button>

Pump power: {power}

<button onclick={() => power++}>+</button>
親コンポーネント
<script>
	import Child from './Child.svelte';

	let size = $state(15);
	let burst = $state(false);

	function reset() {
		size = 15;
		burst = false;
	}
</script>

<Child
	inflate={(power) => {
		size += power;
		if (size > 75) burst = true;
	}}
	deflate={(power) => {
		if (size > 0) size -= power;
	}}
/>

{#if burst}
	<button onclick={reset}>new balloon</button>
	<span class="boom">💥</span>
{:else}
	<span class="balloon" style="scale: {0.01 * size}">
		🎈
	</span>
{/if}

<style>
	span {
		position: fixed;
		left: 0;
		top: 0;
		width: 100%;
		height: 100%;
		font-size: 100vh;
		text-align: center;
		line-height: 1;
		pointer-events: none;
	}

	.balloon {
		transition: scale 0.2s;
	}

	.boom {
		animation: boom 0.5s forwards;
	}

	@keyframes boom {
		0% {scale: 0.6}
		25% {scale: 0.75}
		100% {scale: 0}
	}
</style>

さいごに

Svelte5でcreateEventDispatcher関数が非推奨になったことにより、createEventDispatcher周りのボイラープレートが削減されたり、学習コストが減りました。
propsになったことでどういうイベントを必要としているのかが明確になり、処理が追いやすくなったと思います。

3
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?