LoginSignup
14
12

More than 3 years have passed since last update.

Vue.js における Component 間のデータの受け渡しまとめ

Last updated at Posted at 2020-07-04

Overview

Vue.js を使っていて、この Component 間の関係だとどうやって data 渡すんだっけな...?
となることが多いので方法はいろいろあると思いますが、自分がよくやるやり方をこの記事にまとめておきます。
(他にもこんなやり方あるよ!という知見ありましたら教えていただけますと幸いです :pray: )

親 → 子

親 Component から 子 Component へのデータの受け渡しは、
親 Component で data を v-bind して、子 Component で props で data を引き取ります。

Sample Code

  • Parent.vue ( v-bind で data を渡す)
<template>
  <div id="parent">
    <child v-bind:messageFromParent="this.message" />
  </div>
</template>

<script>
import Child from './Child'

export default {
  name: 'Parent',
  data () {
    return {
      message: 'Hello from Parent!'
    }
  },
  components: {
    child: Child
  },
}
</script>
  • Child.vue ( props で引き取る)
<template>
  <div id="child">
    {{ messageFromParent }}
  </div>
</template>

<script>
export default {
  name: 'Child',
  props: ['messageFromParent']
}
</script>

子 → 親

逆に、子 Component から 親 Component への data の受け渡しは
親 Component で v-on でイベントハンドラを定義しておき、子 Component では $emit で data を持たせて 親 Component で提起しているイベントを発火させます。

※ emit : 放つ、放射する

Sample Code

  • Parent.vue ( v-on でイベントハンドラを定義する)
<template>
  <div id="parent">
    <child v-on:sendMessage="receiveChildMessage" />
    {{ this.childMessage }}
  </div>
</template>

<script>
import Child from './Child'

export default {
  name: 'Parent',
  data () {
    return {
      childMessage: ''
    }
  },
  components: {
    child: Child
  },
  methods: {
    receiveChildMessage (message) {
      this.childMessage = message
    }
  }
}
</script>
  • Child.vue ( $emit で data を持たせつつ、親のイベントを発火する)
<template>
  <div id="child"/>
</template>

<script>
export default {
  name: 'Child',
  data () {
    return {
      message: 'Hello from Child!'
    }
  },
  created () {
    this.$emit('sendMessage', this.message)
  }
}
</script>

子A → 子B

これは実装の方針が人によって分かれそうなのですが、自分は 2つ以上の Component にまたがって data の受け渡しを行う場合 (子A → 親 → 子B 、 親 → 子 → 孫 など) Vuex を使うことが多いです。

※ Vuex についての詳細はこちらをご参照ください。
https://vuex.vuejs.org/ja/

Sample Code

  • store.ts
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

interface State {
  message: string
}

const initState: State = {
    message: ''
};

export default new Vuex.Store({
  state: initState,
  mutations: {
    setMessage(state, { message }: { message: string }) {
      state.message = message;
    }
  }
})
  • Parent.vue ( store を import する)
<template>
  <div id="parent">
    <child-a />
    <child-b />
  </div>
</template>

<script>
import store from './store'
import ChildA from './ChildA'
import ChildB from './ChildB'

export default {
  name: 'Parent',
  store,
  components: {
    child-a: ChildA,
    child-b: ChildB
  },
}
</script>
  • ChildA.vue ( Vuex に data を store する)
<template>
  <div id="child-a"/>
</template>

<script>
export default {
  name: 'ChildA',
  created () {
    this.$store.commit('setMessage', { message: 'Hello from ChildA!' });
  }
}
</script>
  • ChildB.vue ( Vuex から data を参照する)
<template>
  <div id="child-b"/>
  {{ this.message }}
</template>

<script>
export default {
  name: 'ChildB',
  data () {
    return {
      message: ''
    }
  },
  created () {
    this.message = this.$store.state.message
  }
}
</script>

まとめ

  • 親 Component → 子 Component

(親) v-bind:'value'(子) props['value']

  • 子 Component → 親 Component

(子) this.$emit('childHandler', value)(親) v-on:childHandler="parentHandler"

  • 子 Component A → 子 Component B

(子A) Vuex に data を store(子B) Vuex から data を参照

14
12
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
14
12