propsのリアクティビティ
リアクティブデータを子コンポーネントへ渡すとき、子コンポーネントでもリアクティビティを保つためには算出プロパティを用いる 必要があります。
<script setup lang="ts">
import { ref } from "vue";
import ChildComponent from "./ChildComponent.vue";
const data = ref<boolean>(false);
const update = () => {
data.value = !data.value;
}
</script>
<template>
<button @click="update">ボタン</button>
<ChildComponent :data="data" />
</template>
<script setup lang="ts">
import { computed } from "vue";
interface Props {
data: boolean;
}
// const { data } = defineProps<Props>();
// 分割代入するとプロパティのリアクティビティが失われる
const props = defineProps<Props>();
// 算出プロパティでリアクティビティを保つ
const childData = computed<boolean>(() => {
return props.data;
});
</script>
<template>
<div>{{ childData }}</div>
</template>
v-modelを使わないフォームバインディング
参考
v-model
は v-bind
と v-on
をまとめた糖衣構文です。このディレクティブを用いると、簡単な記述でフォームとインスタンスが保持するデータをやりとりさせることができます(双方向データバインディング)。
<script setup lang="ts">
import { ref } from "vue";
const text = ref<string>("Hello, World !");
</script>
<template>
<input v-model="text" />
<p>{{ text }}</p>
</template>
以上の例では <input />
要素の初期値として "Hello, World !"
という文字列が設定されており、<input />
要素の中身を書き換えると text
に値が反映されます。
以上の双方向バインディングを v-bind
と v-on
に分けて書くと以下のようになります。
<script setup lang="ts">
import { ref } from "vue";
const text = ref<string>("Hello, World !");
const onInput = (event: Event) => {
if (event.target instanceof HTMLSelectElement) {
text.value = event.target.value;
}
}
</script>
<template>
<input :value="text" @change="onInput" />
<p>{{ text }}</p>
</template>