今回は子コンポーネントにある、Vuetify3のダイアログを親要素から
表示・非表示させる方法を記します。
Vue2系であれば普通に考えて、スムーズに実装はできますが、
Vue3系は、リアクティブな変数を子コンポーネントに送信することから、
一筋縄ではいきませんでした。
エラーの起こるコード
parent.vue
<template> <Dialog :flag=flag.value></Dialog> </template> <script setup> import Dialog from '@/components/dialog.vue' import { ref } from 'vue' const flag = ref(true); </script>
child.vue
<template> <v-dialog v-model="flag.value" activator="parent" width="auto"> </v-dialog> </template> <script setup> defineProps({ flag:{ type:Boolean, default:false } }) </script>
エラー内容
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'value')
refは、リアクティブなオブジェクト型でString型等であれば省略してtemplateに記述できますが、boolean型は明示的に「.value」を付与してあげる必要があります。
そのため、リアクティブな変数にせよ、.valueはないと怒られてしまいます。
修正
parent.vue
親要素のボタンをクリックしたらダイアログを開くように書いています。
<template> <v-btn @click="flag(true)"></v-btn> <Dialog :flag=flag()></Dialog> </template> <script setup> import Dialog from '@/components/dialog.vue' import { ref } from 'vue' const dialog = ref(false); const flag = (bool = false) => { if(bool){ dialog.value = ref(true); } return dialog; } </script>
child.vue
<template> <v-dialog v-model="flag.value" activator="parent" width="auto"> <v-btn @click="dialog.value = ref(false)">閉じる</v-btn> </v-dialog> </template> <script setup> import { ref } from 'vue' const dialog = ref(false); const props = defineProps({ flag:{ type:Boolean, default:false } }); dialog.value = ref(props.flag); </script>
修正側が多少蛇足な内容も含んでいますが、
flag.valueがundefinedでエラーになることもなくなります。
今更ですが、flag?.valueで解決できたかもと悔恨します。。
おわりに
今回は、親要素で子要素のダイアログを操作する方法を記しました。
何か制限があるかもしれないですが、
子コンポーネント内でダイアログと制御するコードをまとめると正しい挙動になりませんでした。
そのため子でダイアログをつくり、親から呼び出すようにしました。
技術が進化すると、Linuxのディストリビューションのように枝分かれしていき
それぞれの知見が薄くなってきている気がします。なのでググってもうまく答えに辿りつけないことも。。
なのでVue3を使っている私もそろそろ、tsを学ばなくては。と焦っています。
コメント