こんにちは、”はふぃ”です。

コンポーネントは名前付きの再利用可能な Vue インスタンスです。

https://jp.vuejs.org/v2/guide/components.html

Vue.jsではモジュールをコンポーネント化し、一つのコンポーネントの中で複数のコンポーネントを呼ぶことが多いです。

この場合に、呼んでいる方のコンポーネントを「親」、呼ばれる側のコンポーネントを「子」と言います。

< parentConponent.vue >

<template>
  <div>
    <child-component />
    <child-component />
    <child-component />
  </div>
</template>

<script>
  import childComponent from './childComponent'

  export default {
    components: {
      childComponent
    }
  }
</script>

< childComponent.vue >

<template>
  <div>{{ message }}</div>
</template>

<script>
  export default {
    data () {
      return {
        message: 'Hello World!'
      }
    }
  }
</script>

この時、親子間でデータを受け渡す必要がある場合があると思いますが、親から子に渡す場合にはpropsを利用します。

プロパティ — Vue.js

https://jp.vuejs.org/v2/guide/components-props.html

では、子から親にデータを渡す際にどうするのかについていくつか方法があるので説明します。

方法

$emit

vm.$emit( eventName, […args] )

https://jp.vuejs.org/v2/api/index.html#vm-emit

$emitを利用すると子コンポーネントから親コンポーネントのメソッドを呼び、データを受け渡すことが可能です。

< parentComponent.vue >

<template>
  <div>
    <child-component
      @parentMethod="updateMessage"
    ></child-component>
    <!-- 'Hello World!'が表示されます -->
    <p>{{ message }}</p>
  </div>
</template>

<script>
  import childComponent from './childComponent'

  export default {
    data () {
      return {
        message: ''
      }
    },
    components: {
      childComponent
    },
    methods: {
      updateMessage (message) {
        this.message = message
      }
    }
  }
</script>

< childComponent.vue >

<template>
  <div></div>
</template>

<script>
  export default {
    data () {
      return {
        message: 'Hello World!'
      }
    },
    mounted () {
      this.$emit('parentMethod', this.message)
    }
  }
</script>

$listeners

子コンポーネントから親コンポーネントへは$emitでデータを受け渡すことが可能ですが、孫コンポーネント(子コンポーネントの子)から親コンポーネントのメソッドを呼ぶには、$emitを2度使ってデータを孫 → 子 → 親と渡す必要があります。その際に$listenersを利用することでより分かりやすく記述することが可能です。

< parentComponent.vue >

<template>
  <div>
    <child-component
      @parentMethod="updateMessage"
    ></child-component>
    <!-- 'Hello World!'が表示されます -->
    <p>{{ message }}</p>
  </div>
</template>

<script>
  import childComponent from './childComponent'

  export default {
    data () {
      return {
        message: ''
      }
    },
    components: {
      childComponent
    },
    methods: {
      updateMessage (message) {
        this.message = message
      }
    }
  }
</script>

< childComponent.vue >

<template>
  <grand-child-component
    @childMethod="$listeners['parentMethod']"
  ></grand-child-component>
</template>

<script>
  import grandChildComponent from './grandChildComponent'
  
  export default {
    components: {
      grandChildComponent
    }
  }
</script>

< grandChildComponent.vue >

<template>
  <div></div>
</template>

<script>
  export default {
    data () {
      return {
        message: 'Hello World!'
      }
    },
    mounted () {
      this.$emit('childMethod', this.message)
    }
  }
</script>

まとめ

子コンポーネントを再利用する際などに、$emitで呼ぶ親コンポーネントのメソッドが必要なことがわからないことが多いので、コメントなど利用して明記した方がいいかもしれません。

投稿者: はふぃ

若手のWEBフロントエンジニア。最近はバレーボールにハマってます!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA