Vue.jsコンポーネント間の値の受け渡し

プログラミング

こんにちは。現役フリーランスWebエンジニアの@Masaweb4です。

未経験からエンジニアに転職した経験やプログラミングに関する内容を発信しています。

Vue.jsのコンポーネント間の値の受け渡し方がわからない。いろいろな方法があるよね?

こんな疑問を解決していきます。

  1. 親コンポーネントから子コンポーネントへの値はpropsで渡す
  2. 子コンポーネントから親コンポーネントへ値は$emitを使える
  3. 規模が大きめのシステムの場合は値を渡す時はVuexを使う

この記事では上記の内容を知ることができます。初学者向けの内容となっています。

Vue.jsは日本ではReactと並ぶ人気のJavaScriptフレームワーク。2020年も人気上昇中ですね。そろそろjQueryを卒業してVue.jsを始めましょう。では本題に入っていきます。

Contents

  1. Vue.jsのコンポーネントについて
  2. 親から子へのデータの受け渡しはprops
    1. 子コンポーネントで値を受け取るにはpropsを使う
    2. propsではバリデーションも書ける
  3. 子から親へのデータの受け渡し
    1. 子コンポーネントで親に値を渡す時には$emitが使える
    2. $emitは子から親のイベントを発火させるために使える
  4. まとめ

Vue.jsのコンポーネントについて

コンポーネントは部品という意味で、コンポーネント化しておくことで、その部品を使いたい場所でimportして使えるみたいなものですね。

一番上のコンポーネントが、いろんな部品をimportして一つの画面を構成しています。

親コンポーネントから子コンポーネントに値を渡したり、さらに孫コンポーネントに値を渡したり。また、逆もあり孫から別の孫に渡す必要があったりします。

そうすると普通に孫→子→親、そして別の子→孫みたいなことをすると複雑になってしまうわけです。

この後は実際に値の受け渡しについて記述していきます。

親から子へのデータの受け渡しはprops

親コンポーネントから子コンポーネントの値の受け渡しについて説明します。

以下はサンプルコード

App.vue

<template>
  <div id="app">
    <Header msg="〇〇株式会社"/>
  </div>
</template>

<script>
import Header from './components/Header.vue'

export default {
  name: 'App',
  components: {
    Header
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

Header.vue

<template>
  <div>
    {{ msg }}
  </div>
</template>

<script>
export default {
  name: 'Header',
  props: ['msg']
}
</script>

<style scoped>

</style>

子コンポーネントで値を受け取るにはpropsを使う

上のソースコードで親はApp.vueで子がHeader.vueになります。App.vueにHeader.vueをimportしてます。以下の部分で子のコンポーネントにmsgという名前で値を渡しています。

<Header msg="〇〇株式会社"/>

子のコンポーネントの方は「props」というプロパティを使い、配列(オブジェクトでも可能)でなっていてmsgという名前で値を受け取ることができます。

props: ['msg']

header

めちゃくちゃシンプルな画面ができましたヽ(´ー`)ノ

propsではバリデーションも書ける

propsでは配列ではなく、オブジェクトでも書けます。以下のような感じ。msgにStringという型を設定しています。型が違うとエラーになります。

  props: {
    msg: String
  }

さらにmsgもオブジェクトにして以下のように書くことも可能。親のmsgを消すと子の方ではdefaultの’ようこそ’が表示されるようになります。

  props: {
    msg: {
      type: String,
      default: 'ようこそ'
    }
  }

子から親へのデータの受け渡し




子から親にデータを渡す方法はいくつかあるので、紹介していきます。ちょっとつまらないサンプルコードを準備しました。

親コンポーネントから子コンポーネントへ値を渡す

横線の上の方が子コンポーネント、下が親コンポーネントです。子コンポーネントの「+ 1」ボタンをクリックすると親に値が渡り、それを表示しています。

App.vue

<template>
  <div id="app">
    <Header v-on:count-up="parent = $event" />
    <hr />
    <p>犬は{{ parent }}匹飼っています。</p>
  </div>
</template>

<script>
import Header from './components/Header.vue'

export default {
  name: 'App',
  components: {
    Header
  },
  data() {
    return {
      parent: 0
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

Header.vue

<template>
  <div>
    <p>犬は何匹飼っていますか?</p>
    <p><button @click="countUp"> + 1 </button></p>
  </div>
</template>

<script>
export default {
  name: 'Header',
  data() {
    return {
      children: 0
    }
  },
  methods: {
    countUp() {
      this.$emit('count-up', this.children += 1)
    }
  }
}
</script>

子コンポーネントで親に値を渡す時には$emitが使える

子コンポーネントにある「 + 1 」ボタンをクリックするとcountUpメソッドが呼ばれ、$emitを使い現在の値に+1して、count-upという名前で親に渡しています。

親はv-on:count-up=”parent = $event”で値を受け取っています。

ちょっと面倒ですね。

$emitは子から親のイベントを発火させるために使える

$emitは値を渡さなくても親のメソッドのイベント発火用にも使える。

App.vue

<template>
  <div id="app">
    <Header v-on:count-up="countUp()" />
    <hr />
    <p>犬は{{ parent }}匹飼っています。</p>
  </div>
</template>

<script>
import Header from './components/Header.vue'

export default {
  name: 'App',
  components: {
    Header
  },
  data() {
    return {
      parent: 0
    }
  },
  methods: {
    countUp() {
      return this.parent++
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

Header.vue

<template>
  <div>
    <p>犬は何匹飼っていますか?</p>
    <p><button @click="countUp"> + 1 </button></p>
    <!-- {{ count }} -->
  </div>
</template>

<script>
export default {
  name: 'Header',
  data() {
    return {
      children: 0
    }
  },
  methods: {
    countUp() {
      this.$emit('count-up')
    }
  }
}
</script>

最初に書いたサンプルソースの以下の部分では$emit()に二つの引数を渡していました。けれども今回のサンプルソースでは引数が一つで値は渡していない。

this.$emit('count-up', this.children += 1)

親コンポーネントの以下の部分ではcountUp()メソッドが呼ばれてカウントアップしている。

<Header v-on:count-up="countUp()" />

ただ単に親のメソッドを子が発火させるという使い方もできる例でした。

子から親に値を渡す場合は、$emitよりもvuexというものを使う方が一般的で、そちらの使い方も別途書いていこうかなと思います。




まとめ

まとめ

上では$emitを使い親に値を渡すということをしていました。小さいプロジェクトで子から親だけの場合は、$emitを使うということもありかもですが、子から親、さらに別の子へデータを渡すという場合もあります。

子から親に$emitして親から別の子にpropsで渡してみたいなことをしなければならない。そんな時には一般的にはVuexを使う方がよいとされています。

Vuexを使うと子と子でデータの共有ができたりするため、多くのプロジェクトはVuexを使っています。Vuexについては別記事で紹介しようと思います。


MEMO
  1. 未経験の方は早めに目標を決めましょう。
  2. 何を作りたいか、どんなものを作りたいか考える。そしてそのために何を学ぶか調べます。
  3. あとは独学でやってみる(プログラムを書いてみる)
  4. 独学で実績(公開できるレベルのもの)を作れるなら転職活動・就職活動をしてみる。
  5. 難しい場合はスクールに通い実績を作り、早めに就職する。