21
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Svelte3 親子コンポーネント間でデータを受け渡す

Last updated at Posted at 2019-06-09

親 → 子に値を渡す

https://svelte.dev/tutorial/declaring-props
チュートリアルを参考にして書いてみる。

  • 親コンポーネント: 子コンポーネントのプロパティに設定するだけ
  • 子コンポーネント: exportを付けて変数宣言しとくだけ

親の値が変更された場合、子の値も自動で変わる。

親コンポーネント

<script>
	import Child from './Child.svelte';
	let parentCnt = 0
	let childCnt = 0
	function add() {
		parentCnt++;
	}
</script>

<div>親: {parentCnt}</div>
<div>子: {childCnt}</div>
<button on:click="{add}">Parent Button</button>

<Child parentCnt={parentCnt} childCnt={childCnt}/>

子コンポーネント

<script>
	export let parentCnt;
	export let childCnt;
	function add() {
		childCnt++;
	}
</script>

<div>親: {parentCnt}</div>
<div>子: {childCnt}</div>
<button on:click="{add}">Child Button</button>

上のコードを実行したときの動きは以下のようになる。

  • Parent Buttonを押す
    • 親のparentCntがカウントアップされる
    • 子のparentCntが親と同じ値に書き換わる
  • Child Buttonを押す
    • 子のchildCntがカウントアップされる
    • 親のchildCntは変化しない

子 → 親に値を渡す

https://svelte.dev/tutorial/component-events
dispatcherを使って親コンポーネントイベントを呼んで渡せばよいみたい。

最初に使ったコードを使って、Child Buttonが押されたら
親のchildCntにも子コンポーネントでボタンをした数を渡すようにしてみる。

  • 親コンポーネントの変更点
    • 子コンポーネントにon:updateChildイベントを追加
  • 子コンポーネントの変更点
    • createEventDispatcherをインポート
    • dispatchを実行してupdateChildイベントを発火する

親コンポーネント

<script>
	import Child from './Child.svelte';
	let parentCnt = 0
	let childCnt = 0
	function add() {
		parentCnt++;
	}
	function updateChild(event) {
		childCnt = event.detail.cnt
	}
</script>

<div>親: {parentCnt}</div>
<div>子: {childCnt}</div>
<button on:click="{add}">Parent Button</button>

<Child parentCnt={parentCnt} childCnt={childCnt} on:updateChild={updateChild}/>

子コンポーネント

<script>
	import { createEventDispatcher } from 'svelte';

	const dispatch = createEventDispatcher();

	export let parentCnt;
	export let childCnt;
	function add() {
		childCnt++;
		dispatch('updateChild', { cnt: childCnt });
	}
</script>

<div>親: {parentCnt}</div>
<div>子: {childCnt}</div>
<button on:click="{add}">Child Button</button>

孫 → 親に値を渡す

https://svelte.dev/tutorial/event-forwarding
親 → 子 → 孫みたいに何個かコンポーネントがネストされている場合に
孫から親までデータ渡したいときの書き方。

親コンポーネント(変更無し)

<script>
	import Child from './Child.svelte';
	let parentCnt = 0
	let childCnt = 0
	function add() {
		parentCnt++;
	}
	function updateChild(event) {
		childCnt = event.detail.cnt
	}
</script>

<div>親: {parentCnt}</div>
<div>子: {childCnt}</div>
<button on:click="{add}">Parent Button</button>

<Child {parentCnt} {childCnt} on:updateChild={updateChild}/>

子コンポーネント

<script>
	import Child2 from './Child2.svelte';
	import { createEventDispatcher } from 'svelte';

	const dispatch = createEventDispatcher();

	export let parentCnt;
	export let childCnt;

	function updateChild(event) {
		dispatch('updateChild', event.detail);
	}
</script>

<Child2 {parentCnt} {childCnt} on:updateChild={updateChild}/>

孫コンポーネント

<script>
	import { createEventDispatcher } from 'svelte';

	const dispatch = createEventDispatcher();

	export let parentCnt;
	export let childCnt;
	function add() {
		childCnt++;
		dispatch('updateChild', { cnt: childCnt });
	}
</script>

<div>親: {parentCnt}</div>
<div>子: {childCnt}</div>
<button on:click="{add}">Child Button</button>

孫から子のupdateChild → 子から親のupdateChildにイベントを伝達していく感じ。

中間コンポーネントになる子コンポーネントに関しては
特にやること無ければ以下のようにdispatchを省略して書くことが可能。

コンポーネントイベントに何もイベント設定しなければイベントが転送される仕組みになっている。

<script>
	import Child2 from './Child2.svelte';

	export let parentCnt;
	export let childCnt;
</script>

<Child2 {parentCnt} {childCnt} on:updateChild/>

メモ

省略系

親コンポーネントの変数名が、子コンポーネントのプロパティと同じ名前なら以下のようにキーを省略することも可能

<Child childCnt={childCnt}/><Child {childCnt}/>

キャメルケース・スネークケースのプロパティ

子コンポーネントに定義されているプロパティ名がキャメルケース・スネークケースの時は
子に定義されているプロパティ名をそのままの使う。

※Vuejsみたいにケバブケースにする必要はない

<Child hoge={1} hogeHoge={2} hoge_hoge={3}/>
<script>
	export let hoge;
	export let hogeHoge;
	export let hoge_hoge;
</script>

オブジェクトが持つプロパティを一気に子に渡す

オブジェクトのキーを全部、子コンポーネントに渡したい場合。

親コンポーネント

<script>
	import Child from './Child.svelte';
	let obj = { hoge: 1, fuga: 'fuga' }
</script>

<Child hoge={obj.hoge} fuga={obj.fuga}/>

子コンポーネント

<script>
	export let hoge;
	export let fuga;
</script>

上のようにバラバラで渡してもいいけど以下のようにスプレッド構文使ったほうが楽。

<Child {...obj}/>

以下のようにオブジェクトを子に渡す事もできる。
型定義とかしてる訳じゃないので何入ってるか分からないのであまり良いとは思えないけど。

<Child hoge={obj}/>

DOMイベントを親に転送する

dispatchを使って親のDOMイベントを発火させる事もできるが
イベント転送することでより簡単に書くことができる。

親コンポーネント

<script>
	import Child from './Child.svelte';
	let cnt = 0
	function add() {
		cnt++;
	}
</script>

<div>cnt: {cnt}</div>
<Child {cnt} on:click={add}/>

子コンポーネント

<script>
	export let cnt;
</script>

<button on:click>Add</button>

上の記述と、下のdispatchを使った記述は同等。

<script>
	import { createEventDispatcher } from 'svelte';

	const dispatch = createEventDispatcher();

	export let cnt;
	function click() {
		dispatch('click');
	}
</script>

<button on:click="{click}">Add</button>

ちょい注意

ボタンクリック時とかのイベント転送については
on:clickとかon:changeとかのDOMイベントの話で
オリジナルのコンポーネントイベントについてはダメっぽい。

なので以下のコードはイベントが発火されず何もおこならない。

親コンポーネント

<script>
	import Child from './Child.svelte';
	let cnt = 0
	function add() {
		cnt++;
	}
</script>

<div>cnt: {cnt}</div>
<Child {cnt} on:hoge={add}/>

子コンポーネント

<script>
	export let cnt;
</script>

<button on:hoge>Add</button>
21
13
0

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
21
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?