【Vue.js】コンポーネント間でデータをやりとりする方法|props・emit・storeの使い分け

【Vue.js】コンポーネント間でデータをやりとりする方法|props・emit・storeの使い分け Vue.js

Vue.jsでは、アプリケーションを複数のコンポーネントに分割して開発するのが一般的です。その際に重要となるのが、コンポーネント間のデータのやりとりです。本記事では、propsemitVuex(もしくはPinia)などのストアを使って、適切にデータをやりとりする方法を解説します。

propsで親から子へデータを渡す

propsは、親コンポーネントから子コンポーネントへデータを渡すための仕組みです。読み取り専用であり、子コンポーネント側でpropsを直接書き換えることはできません。

// 親コンポーネント
<template>
  <ChildComponent :message="parentMessage" />
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: { ChildComponent },
  data() {
    return {
      parentMessage: 'こんにちは'
    };
  }
};
</script>
// 子コンポーネント(ChildComponent.vue)
<template>
  <p>{{ message }}</p>
</template>

<script>
export default {
  props: ['message']
};
</script>

emitで子から親へイベント通知

emitは、子コンポーネントから親コンポーネントに対してイベントを通知する仕組みです。ボタンのクリックなどを契機にデータを親に渡したいときに便利です。

// 子コンポーネント
<template>
  <button @click="notifyParent">通知</button>
</template>

<script>
export default {
  methods: {
    notifyParent() {
      this.$emit('child-event', '子からのメッセージ');
    }
  }
};
</script>
// 親コンポーネント
<template>
  <ChildComponent @child-event="handleChildEvent" />
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: { ChildComponent },
  methods: {
    handleChildEvent(message) {
      console.log('受け取ったメッセージ:', message);
    }
  }
};
</script>

storeを使ってグローバルにデータ共有

兄弟コンポーネントや階層の深いコンポーネント間でデータを共有したい場合は、VuexやPiniaなどの状態管理ライブラリを使うのが適しています。グローバルな状態として一元管理することで、アプリ全体のデータをスムーズに連携できます。

// Piniaの例(store.js)
import { defineStore } from 'pinia';

export const useMainStore = defineStore('main', {
  state: () => ({
    message: ''
  }),
  actions: {
    updateMessage(newMsg) {
      this.message = newMsg;
    }
  }
});
// 使用例(ComponentA.vue)
<template>
  <button @click="store.updateMessage('更新されたメッセージ')">更新</button>
</template>

<script setup>
import { useMainStore } from './store';
const store = useMainStore();
</script>
// 使用例(ComponentB.vue)
<template>
  <p>{{ store.message }}</p>
</template>

<script setup>
import { useMainStore } from './store';
const store = useMainStore();
</script>

使い分けのポイント

コンポーネント間の関係性やアプリの規模によって、以下のように使い分けるのが効果的です。

  • 親 → 子:propsで値を渡す
  • 子 → 親:emitでイベント通知
  • 兄弟や遠い階層間:storeで共有

これらの方法を適切に使い分けることで、Vue.jsアプリのデータフローをシンプルに保ち、保守性の高いコードを書くことができます。