現在、Nuxt3, Vue3, TypeScriptsで開発をしております。
タイトル通り、孫、子、親のバケツリレーを書くことがありましたので、書き方をアップしていきます。
関係する部分のみ記載するため、ご注意ください⚠️
確認と前提
- propsの値は、子コンポーネントでは変更することを推奨されていない。
(挙動としてはできるが、vueの更新などで、できなくなってしまったら、システムとして成り立たなくなることもあるので、プロジェクトではやらない。) - storeを使ったデータの受け渡しもあるが、データの動きがわかりづらくなり、コードが読みづらくなるため、うちのプロジェクトでは推奨されなかった。
孫コンポーネント
inputの枠やその周辺のコンポーネント
<script setup langt="ts">
const props = withDefaults(defineProps<{
val: string,
}>(), {
});
interface Emits {
(e:'commentUpdate', comment: string): void;
}
const emits = defineEmit<Emits>();
</script>
<template>
<textarea
:autocomplete="props.autocomplete" // この値propsで送られてくる。(どんな値が期待されるかを示唆するもの。)
:value="props.val" // 表示は親でする。 上記もだが、propsなくても良い。
@input="emits('commentUpdate', ($event.target as HTMLInputElement).value);”
></textarea>
</template>
子コンポーネント
input枠やその周辺のコンポーネントを含む、その他部分を足したコンポーネント。
<script setup langt="ts">
const props = withDefaults(defineProps<{
comment: string,
}>(), {
});
interface Emits {
(e:'commentUpdate', comment: string): void;
}
const emits = defineEmit<Emits>();
</script>
<template>
<FormInput
:val="props.comment" // 親の値をそのまま孫へ
:width="'100%'"
@commentUpdate="emits('commentUpdate', $event)" // 親へそのまま値を持っていくだけのメソッド。
/>
</template>
ここの$eventは孫の($event.target as HTMLInputElement).value) 入力されたもの。
親コンポーネント
<template>
<Result
:comment='state.comment'
@commentUpdate="state.comment = $event"
>
</template>
// 孫から子供を通ってきた値そのまま、stateに反映。
結論
孫から親へは、emitで値を送る。
親から孫へは、propsで値を送る。
参考
https://zenn.dev/k_kudo/articles/5e60caba140ad7
https://cloudsmith.co.jp/blog/frontend/2020/12/1656030.html