Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

親 → 子に値を渡す

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>
masakurapa
自分の作業メモ的なことを書く感じ。 PHP/Goで開発をしています。 家ではAWS/Svelte3/Goを触りながら色々作って遊んでます。
kaonavi
クラウド人材管理ツール「カオナビ」の製造・販売・サポートを行い、企業の人材管理にイノベーションを起こすことを目的としている会社
https://www.kaonavi.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away