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

Vue.jsのコンポーネント入門

More than 1 year has passed since last update.

規模が大きくなってきたらコンポーネント化しよう

Vue.jsを一番シンプルに書くとこんな感じ。

main.js
<div id="app">
  {{ message }}
</div>

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})

これでもいいけど、規模が大きくなってくるとなかなかメンテナンスが大変になってくる。
またheaderなど、複数画面で共通して使いたい場合もでてくる。

そんなときに便利なのがコンポーネント。

コンポーネントを登録する

コンポーネントを使用する場合、まずは登録が必要となる。

グローバルに使いたい場合

html側の #app #app2 内で my-component のカスタムタグが使えるようになる。

main.js
// Vue.component(tagName, option)でグローバルにコンポーネントを登録
// これで全インスタンスで使えるようになる
// 必ずしもカスタムタグ名を「W3Cルール」にする必要はない

Vue.component('my-component', {
  template: '<div>グローバルで登録したコンポーネントです。</div>'
})

new Vue({
  el: '#app'
})

new Vue({
  el: '#app2'
})

スコープを切って使いたい場合

複数のインスタンスが存在する場合、スコープを切って特定のインスタンスでだけ使えるようにもできる。

main.js
// スコープを切ってコンポーネントを登録したいときはまず変数におく
// コンポーネントを登録したapp2でのみコンポーネントが読み込まれる

const Scoped = {
    template: '<div>スコープを切ったコンポーネント</div>'
}

new Vue({
  el: '#app',
})

new Vue({
  el: '#app2',
  components: { //Scopedが使える
    'scoped-component': Scoped,
  }
})

コンポーネントにデータを持たせる

コンポーネントの場合、データを関数として返す必要がある。

main.js
// コンポーネントにデータを渡すときは関数にしてreturnしないといけない
const DataComp = {
    template: '<div>私の名前は{{name}}です</div>',
    data: ()=> {
      return {
        name: "花子"
      }
    },
}

new Vue({
    el: '#app2',
    components: {
      'data-component': DataComp,
    }
})

親子間でのデータの受け渡し

コンポーネントは基本的に単一では使用せず、親であるインスタンスやコンポーネントと一緒に使うことになる。

メンテナンスの手間や拡張の可能性を考慮すると、それぞれのコードはできるだけ独立した形にしてデータを受け渡すような実装が理想。
親子間でのデータ受け渡しは直接参照できないため、以下のようなものを利用する。

親から子:props

親のデータを参照する場合、子コンポーネント内の props オプションでプロパティを宣言する。
この val は親のデータが入ってくるハコを作っているだけなので、名前はなんでも良い。

main.js
// 子コンポーネント(データが入ってくるハコを用意)
const PropsComp = {
    props: ['val'],
    template: '<div>朝起きたら{{val}}といいましょう。</div>',
}

// 親コンポーネント
new Vue({
    el: '#app2',
    data: {
      message: "good morning",
      hoge: "hoge"
    },
    components: {
      'props-component': PropsComp
    }
})

親コンポーネントのmessageをプロパティに渡せば(hogeでもいいけど) 「朝起きたらgood morningといいましょう。」 と表示されるようになる。

index.html
<div id="app2">
    <props-component :val="message"></props-component>
</div>

子から親:emit

子コンポーネントのボタンのクリック数を親コンポーネントで参照する場合を考える。

Screen Shot 2018-01-17 at 18.03.52.png

main.js
// 子コンポーネント
Vue.component('button-counter', {
    template: '<button v-on:click="increChild">{{ counter }}</button>',
    data:  ()=> {
        return {
            counter: 0
        }
    },
    methods: {
        increChild: function () {
            this.counter += 1
            this.$emit('increment')
        }
    },
})

// 親コンポーネント
new Vue({
    el: '#counter-event-example',
    data: {
        total: 0
    },
    methods: {
        increParent: function () {
            this.total += 1
        }
    }
})
index.html
    <div id="counter-event-example">
      <p>クリック数合計:{{ total }}</p>
      <button-counter v-on:increment="increParent"></button-counter>
    </div>

イベントの伝達順序

  1. 子コンポーネントの数値が加算される: increChild
  2. increment イベントが発火される: $emit('increment')
  3. 親コンポーネントの数値が加算される: increParent

キャメルケース?ケバブケース?どっち?

カスタムタグ名 プロパティ名を書くときは「W3Cルール」(全て小文字で、ハイフンが含まれている ≒ ケバブケース)ではなく、キャメルケースでもOK。

main.js
const camelKebab = {
    props: ['myMessage'], //プロパティ名
    template: '<div>This is {{myMessage}}.</div>',
}

new Vue({
    el: '#app2',
    data: {
      message: "good morning",
    },
    components: {
      'camelKebab': camelKebab //カスタムタグ名
    }
})

ただし、htmlの属性は case-insensitive(大文字小文字を区別しない) ため 実際に使用する場合は ケバブケース する必要がある。

index.html
<div id="app2">
  <!--これはだめ-->
  <!--<camelKebab></camelKebab>-->

  <camel-kebab my-message="message"></camel-kebab>
</div>
キャメル ケバブ
Vue側
html側 X

A. キャメルケースを使ってもいいが、html側では必ずケバブケースにする

shosho
Qiitaには忘れそうなこと、勉強したことをメモしてます。
https://shosho-egg.hateblo.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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした