親 → 子に値を渡す
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>