beta

Vue.jsで関数型コンポーネントの中で@clickでmethodを実行する

Vue.jsで、スクリプト処理を軽くできる「関数型コンポーネント」多用していると、どうしても@clickなどでmethodを処理したくなります。そのやり方をまとめました。

公開日:2019年8月23日

想定ケース

ボタンなど、小さな部品を関数型コンポーネントとして管理している時に、ボタンを押した時の処理を都度変えたい、そんな時に使える方法です。

  • 呼び出し元コンポーネント(App.vue)
  • 関数型コンポーネント(Btn.vue)

ダメなケース

素直に関数型コンポーネントにmethodsを書いてみる

まずは、普通にBtn.vueにmethodを書いてみます。

<template functional>
  <span class="button" @click="addSomthing()">{{props.label}}</span>
</template>

<script>
export default {
  props: ['label'],
  methods: {
    addSomthing() {
      console.log('add something');
    },
  }  
}
</script>

ブラウザのコンソールを確認すると、vm.addSomthingがありませんというエラーになります。

読み出し元からディレクティブに付与してみる

では、呼び出し元の「App.vue」で「Btn.vue」を呼び出す時に付与してみたらどうでしょう。

<template>
  <Btn :label="'カートに入れる'" @click="addSomthing" />
</template>

<script>
import Btn from "@/components/atom/Btn.vue";

export default {
  components: {
    Btn
  },
  methods: {
    addSomthing() {
      console.log('add something');
    },
  }
}
</script>

反応しません。ダメでした。

これが正解!

functionもpropsとして渡す

基礎から学ぶ Vue.jsによると、propsで受け取れる値は、

  • String:文字列:’1’
  • Number:数値:1
  • Boolean:真偽値:true, false
  • Function:関数:function() {}
  • Object:オブジェクト:{ name: ‘foo’ }
  • Array:配列:[1, 2, 3], [{ id: 1 }, { id: 2 }]
  • カスタム:インスタンス:new Cat()
  • null:すべての型:1, ‘1’, [1]

となっています。関数がありますね。

ということは、propsでfucntionを渡してしまえば良さそうです。

呼び出し元である「App.vue」では、

<template>
  <Btn :label="'カートに入れる'" :func="addSomthing" />
</template>

<script>
import Btn from "@/components/atom/Btn.vue";

export default {
  components: {
    Btn
  },
  methods: {
    addSomthing() {
      console.log('add something');
    },
  }
}
</script>

として、関数を登録しつつ、propsでBtnに対して「addSomthing」関数を渡します。

一方、関数型コンポーネント(Btn.vue)側は、

<template functional>
  <span class="button" @click="props.func">{{props.label}}</span>
</template>

<script>
export default {
  props: ['label', 'func'],
}
</script>

として、@clickにprops.funcで関数名を受け取ればOKです。

これで、呼び出し元で設定した「addSomthing」methodが、関数型コンポーネント「Btn」をクリックした際に実行されました。


考えてみたら簡単なんですが、ここに気づくのにかなり時間がかかってしまったので、同じようなことをしようとしている方の参考になれば幸いです。