【vue.js】コンポーネント間のメソッドの呼び出し|親から子(ref)、子から親(emit)

投稿者: | 2018年10月21日

Vue.jsで別コンポーネントに定義しているメソッドの呼び出し方についてメモしておきたいと思います。別コンポーネントの呼び出しは大きく2つ存在します。

  1. 親から子(ref)
  2. 子から親(emit)

最初にサンプルの動作イメージです。

  • 親が子どもに小遣いをあげる。(親から子に金額を渡します:ref)
  • 子が親の財布からお金を盗る笑。(子から親に金額を渡します:emit)

①親から子のコンポーネントの呼び出し(ref)

属性を渡すだけでしたらpropsが使えるのですが、子のコンポーネントに記述のあるメソッドを呼び出す場合はrefがとても便利です。親からすると、自分のコンポーネントに記載があるメソッドと同じような記述で子のコンポーネントを呼び出すことができます。

親コンポーネント「parent」

<template>
  <div>
    <h2>親</h2>
    <p><button @click="callChildMethod01">子ども呼び出し①</button></p>
    <p>
        <input type="text" v-model="kozukai">円
        <button @click="callChildMethod02">小遣いをあげる</button>
    </p>
    <child-app ref="taro"></child-app>
  </div>
</template>

<script>
import childApp from './childApp.vue'
export default {
  data () {
    return {
      kozukai: 0
    }
  },
  components: {
    childApp
  },
  methods: {
    callChildMethod01 () {
      this.$refs.taro.child_method_01()
    },
    callChildMethod02 () {
      this.$refs.taro.child_method_02(this.kozukai)
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

 

子どものコンポーネント「childApp」

<template>
  <div>
    <h2>子ども</h2>
    おこずかい:{{number}}円
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      number: 0
    }
  },
  methods: {
    child_method_01 () {
      alert('親から呼ばれました')
    },
    child_method_02 (tmp) {
      this.number = this.number + parseInt(tmp)
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

ポイント

  • 【親】template内の子コンポーネント呼び出しの際に「ref」で名前を追加している。例では「taro」。
<child-app ref="taro"></child-app>
  • 【親】子どもの中のメソッドをrefを使って呼び出す
methods: {
  callChildMethod01 () {
    this.$refs.taro.child_method_01()
  },
  callChildMethod02 () {
    this.$refs.taro.child_method_02(this.kozukai)
  }
}

この部分。01は引数なし、02は引数ありの例です。

  • 【子】子の側はとくに追加の記載は必要なし。

こんな感じです。親の中で子のコンポーネントを呼び出す際に「ref」で名前を追加するだけで、refを使って子のコンポーネントを呼び出すことができます。

②子から親のコンポーネントの呼び出し(emit)

こちらはemitを使います。emitの利用イメージですが、子から親に対してイベントを通知し、親側でイベントをハンドリングして処理を行うイメージです。子から発火するイベントにはパラメータを渡すことも可能です。

親コンポーネント

<template>
  <div>
    <h2>親</h2>
    お財布の中身:{{money}}
    <p><button @click="callChildMethod01">子ども呼び出し①</button></p>
    <p>
        <input type="text" v-model="kozukai">円
        <button @click="callChildMethod02">小遣いをあげる</button>
    </p>
    <hr>
    <child-app ref="taro"
      @callParent="callFromChild"
      @stealMoney="stealMoney"
      ></child-app>
  </div>
</template>

<script>
import childApp from './childApp.vue'
export default {
  data () {
    return {
      money: 10000,
      kozukai: 0
    }
  },
  components: {
    childApp
  },
  methods: {
    callChildMethod01 () {
      this.$refs.taro.child_method_01()
    },
    callChildMethod02 () {
      this.money = this.money - this.kozukai
      this.$refs.taro.child_method_02(this.kozukai)
      this.kozukai = 0
    },
    callFromChild () {
      alert('子どもから親が呼ばれました。')
    },
    stealMoney (tmp) {
      this.money = this.money - tmp
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

 

子コンポーネント

<template>
  <div>
    <h2>子ども</h2>
    <p>おこずかい:{{money}}円</p>
    <p><button @click="call_parent01">親を呼ぶ</button></p>
    <p><input type="text" v-model="kingaku">円<button @click="call_parent02">親の財布から盗る</button></p>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      money: 0,
      kingaku: 0
    }
  },
  methods: {
    child_method_01 () {
      alert('親から子どもが呼ばれました。')
    },
    child_method_02 (tmp) {
      this.money = this.money + parseInt(tmp)
    },
    call_parent01 () {
      this.$emit('callParent')
    },
    call_parent02 () {
      this.$emit('stealMoney', this.kingaku)
      this.money = this.money + parseInt(this.kingaku)
      this.kingaku = 0
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

ポイント

  • 【子】親のメソッドを呼び出したいタイミングでemitを使って親にイベントを通知します。
call_parent01 () {
  this.$emit('callParent')
},
call_parent02 () {
  this.$emit('stealMoney', this.kingaku)
  this.money = this.money + parseInt(this.kingaku)
  this.kingaku = 0
}

 

02はパラメータも渡す例です。

  • 【親】emitで渡されたイベントをハンドリングします。
<child-app ref="taro"
      @callParent="callFromChild"
      @stealMoney="stealMoney"
      ></child-app>

template内のchild-appの呼び出しにイベントをバインドする記述を追加すればOK。

さいごに

こんな感じで簡単にコンポーネント間のメソッドの呼び出しが、親⇒子、子⇒親の双方向で簡単に実装できました。簡単なのはいいのですが、直観に任せて呼び出しを実装していくと、プログラム全体が迷路のように複雑になりかねないなと感じ、コーディングのルール決めみたいなのが重要なんだろうなと感じました。

vue.jsは日々勉強しながらWebサービス作っていますので、またメモにまとめていきたいと思います。


カツオが開発したWebサービスです。

「セールサーチ」ネットショップのセール情報の検索サイト!

平成の想い出を気軽に年表にしてシェアすることができるサービスです。ぜひ使ってみてください。

コメントを残す

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