Vueでemitを使わずpropsで関数を渡してReactっぽくしてみる
こんにちは。昨年10月にSHIFTに入社した三輪です。SHIFT社内のプロダクト開発に従事しております。最近は発足したばかりの基盤開発チームにスクラムの体制を取り入れようとしております。
基盤開発チームではアーキテクチャとしてマイクロサービスを採用しており、各サービスのフロントエンドはVue.js、バックエンドはExpressで開発を進めています。
Vueはミニマムで素早くフロントエンドを開発するには最適なフレームワークですが、子コンポーネントの動きを親コンポーネントに伝えるためにemitという機能があります。
このemitを使うためには親コンポーネント側で子コンポーネント側のemitの名前を管理する必要があり、親コンポーネントと子コンポーネントが相互に依存しています。開発規模が大きくなってくるとこの相互依存関係が増え、管理するのが非常にしんどくなってしまいます。
出来るならReactのように、情報の流れは親コンポーネント→子コンポーネントの単方向であった方が開発体験は向上します。
そこで今回は、VueでもReactのように親コンポーネントで定義した関数を子コンポーネントに渡してemitを使わなくて済む実装について考察してみます。
関数をpropsで渡す方法
ParentsComponentとChildComponentの2つのコンポーネントを用意します。
// ParentsComponent.vue
ParentComponentの方ではstepとそれを更新するsetStepを定義します。命名とメソッド定義はReactのuseStateライクにしてみました。
そしてこの2つをChildComponentにpropsで渡します。
// ChildComponent.vue
ChildComponent側ではParentComponentから渡ってきたstepとsetStepメソッドを受け取っています。
そしてボタンをクリックされるとsetStepが実行され、stepが+1出来ました。
子コンポーネント側で親コンポーネントのメソッド呼び出しをした場合、thisはどうなる?
jvascriptのthisは厄介で、記述されている箇所によって内容が変化してしまいます。
詳しくはこちらの記事が詳しい。
簡単にいうとthisがメソッドの中で呼び出されているか関数の中で呼び出されているかでthisの中身が変わってしまいます。
結論からいうと、今回の場合はメソッド呼び出しなので、thisの中にはParentComponentが格納されます。
実際にsetStepの中にconsole.log(this)を仕込んで確認してみましょう。
// ParentComponent.vue
...
setStep() {
console.log(this)
this.step = step
}
// console.logの中身
VueComponent {
_uid: 75,
...,
setStep: f(),
step: 2
}
console.logでVueComponentが出力され、その中身にsetStepとstepが存在していることから、thisの中身はParentComponentだということがわかります。
まとめ
この方法であればemitを使わずに済むので、親コンポーネント側が自分のメソッドが子コンポーネント側でどうやって呼び出されるか知っている必要はありません。すなわち、Vueではemitを使うことで親コンポーネントが子コンポーネント側に依存していましたが、その状況を排除することが出来ました。
ただし、この実装方法は「Vueっぽくない」と感じていて、Vueに慣れたエンジニアを混乱させる可能性があるので、チーム開発では実践投入しづらいかもしれないので、emitを使うことの弊害が大きくなってきたときの選択肢として考えておくくらいでいいかもしれません。
_________________________________
お問合せはお気軽に
https://service.shiftinc.jp/contact/
SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/
SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/
SHIFTの導入事例
https://service.shiftinc.jp/case/
お役立ち資料はこちら
https://service.shiftinc.jp/resources/
SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/