背景
Svelteを勉強中です。なかなか面白いと感じましたが、親子関係にあるコンポーネントのデータ(&イベント)やりとりが公式サイトのガイドを見てもピンと来なかったので、メモ。
動作環境
Node v7.4.0
svelte-cli version 1.3.4
svelte version 1.9.1
OS windows10 64bit
まずは簡単なデータやりとり(プロパティ)から
ユーザー情報を親コンポーネントからeachで逐次受け取って表示するように連携させます。
{{#each users as user}}
<UserProfile user={{user}} />
{{/each}}
<script>
import UserProfile from './UserProfile.html';
export default {
components: {
UserProfile
},
data(){
return {
users: [
{name: 'test1', age : 30},
{name: 'test2', age : 40},
{name: 'test3', age : 50}
]
}
}
};
</script>
<p>ユーザー名:{{user.name}}[{{user.age}}歳]</p>
// 結果
ユーザー名:test1[30歳]
ユーザー名:test2[40歳]
ユーザー名:test3[50歳]
上記のように、単なるプロパティの受け渡しは、コンポーネント呼び出しの際にプロパティ名=値
の形式で書いておけば、子供のコンポーネントからは、そのまま{{コンポーネント名}}
で受け取れます。先頭にpropsやoptsなどは必要ありません。
子供で発生したイベントを親側で検知したい
次は、イベントのやりとりです。例として、googleのMaterial Design Liteを利用した汎用コンポーネントを作成したいとします。例として、その中からtext fieldを取り上げます。
子供のコンポーネントは、サイトを参考にベタで書くと
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" name={{name}} id={{name}}>
<label class="mdl-textfield__label" for={{name}}>{{label}}</label>
</div>
こんな感じでしょうか。プロパティとしてnameやlabelを受け取るようにしています。
ここで、inputに入力された情報を親コンポーネントに送りたい、とします。
その場合は、componentメソッドのうち、fireを利用します。
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" name={{name}} id={{name}}
on:keyup="fire('changevalue', {val: event.target.value})">
<label class="mdl-textfield__label" for={{name}}>{{label}}</label>
</div>
fireの第1引数は発火するイベント名を、第2引数では親コンポーネントに引き渡すデータ名をObject形式で記述します。ここでは例としてキーを1文字入力するたびにイベントを発火するようにしています。
こうしておくと、親コンポーネントは次のように書けます。
<MdlTextfield on:changevalue="update(event.val)" name="test" label="あなたの名前は?" />
<p>名前は{{val}}ですね</p>
<script>
import MdlTextfield from './mdl-textfield.html';
export default {
components: {
MdlTextfield
},
data(){
return {
val: ''
}
},
methods: {
update(val) {
this.set({val: val})
}
}
};
</script>
コンポーネント側では、子供が発火したイベント'changevalue'を受け取り、updateメソッドに渡しています。その際、親側のeventオブジェクトには、子供のオブジェクトが渡したデータ名でデータが入ってきます。(子供側で{category: 'test'}
と渡すと、親はevent.category
で'test'が受け取れます)。
まとめ
これで親↔子供間でデータやりとりができます。