■ 要点まとめ(先に結論)

✅ クラスコンポーネントでは

👉 @Prop()@Emit() を組み合わせてv-modelを手作業で作った

✅ Composition APIでは

👉 defineProps()defineEmits() で「v-model」を自動対応できる

つまり、Composition APIのほうが圧倒的に自然にv-modelを扱える


■ クラスコンポーネント版(変換前)

// ファイル名: ChildComponent.vue(クラスコンポーネント版)
<template>
  <input :value="value" @input="onInput" />
</template>

<script lang="ts">
import { Vue, Component, Prop, Emit } from 'vue-property-decorator';

@Component
export default class ChildComponent extends Vue {
  // v-modelで渡されるvalue
  @Prop({ type: String, default: '' }) private value!: string;

  // inputイベントを発火して親に渡す
  @Emit('input')
  onInput(event: Event) {
    return (event.target as HTMLInputElement).value;
  }
}
</script>

クラス版の特徴


■ Composition API版(リファクタリング後)

// ファイル名: ChildComponent.vue(Composition API版)
<template>
  <input :value="modelValue" @input="(e) => emit('update:modelValue', (e.target as HTMLInputElement).value)" />
</template>

<script setup lang="ts">
// 親から渡されるv-model(modelValue)を受け取る
const props = defineProps<{
  modelValue: string
}>();

// 親へイベントを送るためのemit関数
const emit = defineEmits<{
  (e: 'update:modelValue', value: string): void
}>();
</script>

Composition API版の特徴