127
124

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.

vue.jsのカスタムコンポーネントをちゃんと使う

Last updated at Posted at 2015-08-20

カスタムコンポーネントを使おうとして、公式ドキュメントをはじめとしていろんな情報を漁っても、
親から子にdataを渡して子ではテンプレートに表示してるだけ、みたいなシンプルすぎてよくわからないサンプルばかり見つかるので、自分で試しながら理解した点をまとめます。

親からデータを渡された後はコンポーネント側で自立して状態保持・変更を行うようなサンプルを書いてみました。

index.html
<script language="javascript" src="http://cdnjs.cloudflare.com/ajax/libs/vue/1.0.24/vue.js"></script>

<div id="app">
    <pattern-component v-for="pattern in partterns" :pattern="pattern" track-by="$index"/>
</div>

<script>
    var patternComponent = Vue.extend({
        data: function(){
            return { 
                list: ["", "", "×", ""]
            }
        },
        props: [ 'pattern' ],
        methods: {
            change: function(){
                this.pattern++;
                if(this.pattern >= this.list.length){
                    this.pattern = 0;
                }
            },
        },
        computed: {
            mark : function(){
                return this.list[this.pattern];
            },
        },
        template: '<li @click="change">{{mark}}</li>'
    });

    var app = new Vue({
        el: '#app',
        data: {
            partterns: [ 0, 0, 0, 0 ]
        },
        components: {
            'pattern-component': patternComponent
        }
    })
</script>

カスタムコンポーネントの基本的な使い方

公式ドキュメントはなんかつらつら書いてありますが、Vue.extend({})で定義して、Vue.component()で登録して使います。Vue.component()で定義しても動きますが、別ファイルに切り出せるようになるというのはカスタムコンポーネントの利点の一つなので、わざわざ固めてしまうモチベーションはよくわかりませんでした。
参考:http://jp.vuejs.org/guide/components.html#コンポーネントの使用

v-forから渡ってくるデータについて

<my-component v-for="childProp in parentList" :childProp="childProp"/>

みたいな書き方をすると、patentListの1つの要素がmy-componentchildPropに渡されます。
サンプルでは各子コンポーネントに渡すプロパティが同一値であるため、track-byパラメータを指定するようにと[Vue warn]がでました。同一のプロパティで初期化する場合は注意しましょう。

vue.js:1018 [Vue warn]: Duplicate value found in v-for="pattern in partterns": 0. Use track-by="$index" if you are expecting duplicate values.```

参考: https://jp.vuejs.org/guide/components.html#コンポーネントと-v-for

## templateについて
もっと大きく複雑になる場合は、`<template>`を使って別ファイルに切り出して、JSコード側からはidで指定するようにすべきだと思います。
また、いろんなところで子コンポーネントのテンプレート内に親のデータをアサインしているような使い方がされているのを見かけましたが、カスタムコンポーネントとして使うならちゃんと分離しておく方が見通しも再利用性もよくなりそうな気がします。

## methods, computedについて
普通に `new Vue({...})`する時と全く同じように使えました。
カスタムコンポーネント内に定義することによって、親のVMでは実際に表示されるマークについて全く意識する必要がなくなり良い感じです。

## バインディングについて
何も考えずに使うとデフォルトがone-wayバインディングで、子から親への伝搬が行われないので注意が必要です。子から親へ伝搬させたい場合はプロパティを渡す時に `.sync`を指定してやる必要があります。
参考:http://jp.vuejs.org/guide/components.html#Prop-バインディングタイプ


## 感想
- カスタムコンポーネントをちゃんと活用するとファイルが分けられる/責務が分割できる/見通しがよくなるなど一般的なクラス分けの恩恵を受けられそうです。ガンガン使いましょう。
- 今回書いたサンプルの`list`の部分をmixinで拡張すれば、コンポーネントの使い勝手が上がりそうだなと思ったんですが、今回はそこまで手が回らなかったのでmixin拡張しやすいインタフェースについてもそのうち考えます
127
124
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
127
124

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?