【Vue.js】props で渡された値の変更を検知したい
こんにちは!
ラブグラフエンジニアのひろです。
Vue.js にて、 props で渡された値を使ってあれこれしたい時の方法を迷ったので、試したことをまとめます。
やりたかったこと
親コンポーネントで動的に生成され props で渡される値に応じて、子コンポーネントの表示を切り替えたり、子コンポーネント側で値を変えて表示を切り替えたい。
悩んだこと
子コンポーネントで props を直接変更するのは良くない[1]ので、 data で用意したプロパティに代入しようと考えました。
しかし、今回 props で渡される値は親コンポーネントで動的に生成されるので、 created, mounted の時点では undefined になります。
親コンポーネントで値が生成された後に props 経由で受け取ることができる方法、ということで watch, computed などを試してみました。
良さそうな方法
watch を使う。
data() {
return {
selectedPrefectureId: null,
};
},
...
watch: {
specifiedPrefectureId(newValue) {
this.selectedPrefectureId = newValue;
},
},
props: {
specifiedPrefectureId: {
required: false,
type: Number,
},
},
いくつか試した中でもっともマシに見える方法です。
watch を使って props の変更を検知し、それを data で用意したプロパティに代入しました。
これにより親コンポーネントで specifiedPrefectureId が変われば、子コンポーネントの selectedPrefectureId も変わり、子コンポーネントの表示に反映させることができますし、
子コンポーネント側で selectedPrefectureId を変更して表示を変えることもできるようになりました。
(後者の場合は、親コンポーネントと値がズレるので、値を更新するメソッドを props で受け取っておくなどして、親コンポーネントに変更を反映させる処理も必要になります)
検討した方法それぞれについて書いていきます。
watch
- 特定のプロパティに変更があった場合だけに絞って検知できる
- watch の名の通り、値の変更を監視し続けるものなので、変更の検知が1度だけ必要な今回のケースだと少し違和感がある
beforeUpdate
- DOM更新のたびに毎回呼ばれるので、実質的に props の変更を検知できる
- 今回のケースだと関係のない値の更新でも無駄に呼ばれてしまう
computed
(今回やりたかったことには合致しませんでしたが)
値を使って何か表示したいだけなら、キャッシュも効いて、値の変更にも対応できる computed が良さそうでした。
以下は computed で props の値を用いて表示に使う例です。
if (specifiedPrefectureId !== undefined)
を挟むことで、今回の例のような親コンポーネント側でデータ生成前の状態にも対応できますね。
computed: {
selectedPrefectureName(specifiedPrefectureId) {
if (specifiedPrefectureId !== undefined) return "未選択";
return this.prefectures.find((prefecture) => prefecture.id === specifiedPrefectureId).name;
}
}
...
props: {
specifiedPrefectureId: {
required: false,
type: Number,
},
},
終わりに
以上、お読みいただきありがとうございました。
最終的に採用した watch での解決が全方位納得するものではなかったので、他にいい方法が見つかればまた記事にしようと思います。
あまり発生しないケースかもしれませんが、誰かの参考になれば嬉しいです。
Discussion