LoginSignup
5
5

More than 3 years have passed since last update.

Svelteでコンポーネント間のやりとりメモ

Last updated at Posted at 2017-06-26

背景

Svelteを勉強中です。なかなか面白いと感じましたが、親子関係にあるコンポーネントのデータ(&イベント)やりとりが公式サイトのガイドを見てもピンと来なかったので、メモ。

動作環境

Node v7.4.0
svelte-cli version 1.3.4
svelte version 1.9.1
OS windows10 64bit

まずは簡単なデータやりとり(プロパティ)から

ユーザー情報を親コンポーネントからeachで逐次受け取って表示するように連携させます。

apps.html
{{#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>
UserProfile.html
<p>ユーザー名:{{user.name}}[{{user.age}}歳]</p>
// 結果

ユーザー名:test1[30歳]
ユーザー名:test2[40歳]
ユーザー名:test3[50歳]

上記のように、単なるプロパティの受け渡しは、コンポーネント呼び出しの際にプロパティ名=値の形式で書いておけば、子供のコンポーネントからは、そのまま{{コンポーネント名}}で受け取れます。先頭にpropsやoptsなどは必要ありません。

子供で発生したイベントを親側で検知したい

次は、イベントのやりとりです。例として、googleのMaterial Design Liteを利用した汎用コンポーネントを作成したいとします。例として、その中からtext fieldを取り上げます。
子供のコンポーネントは、サイトを参考にベタで書くと

mdl-textfield.html
<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を利用します。

mdl-textfield.html
<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文字入力するたびにイベントを発火するようにしています。
こうしておくと、親コンポーネントは次のように書けます。

apps.html
<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'が受け取れます)。

capture.png

まとめ

これで親↔子供間でデータやりとりができます。

5
5
2

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
5
5