[Vue.js]v-model(双方向バインディング)
公開日:2026-03-11
更新日:2026-03-11
更新日:2026-03-11
1. 概要
v-model(双方向バインディング)で入力欄の値と ref を連動させます。
動作確認:Vite 7.3.1、Vue.js 3.5.25
動作確認:Vite 7.3.1、Vue.js 3.5.25
2. サンプル1
2.1 コード
index.html と src/main.ts は、「Hello, World」で作成したものを使用します。
src/App.vue
実行結果

src/App.vue
コード
<script setup lang="ts">
import { ref } from 'vue';
const value = ref("");
</script>
<template>
<input type="text" v-model="value" /><br /><br />
<button @click="value = ''">クリア</button><br /><br />
{{ value }}
</template>
実行結果

2.2 説明
v-model で ref を指定すると、入力欄の値と ref の値が連動します。
入力欄を変更すると即座に ref に反映され、
ref を変更すると、即座に入力欄に反映されます。
入力欄を変更すると即座に ref に反映され、
ref を変更すると、即座に入力欄に反映されます。
3. サンプル2 - (旧)独自コンポーネントで双方向バインディング
src/components/MyInput.vue
modelValue は、v-model で prop 名を指定しなかった場合のデフォルトの名前です。
prop 名は「v-model:title」のように「v-model:prop名」の形で指定します。
この場合、子コンポーネントでは「:value="props.title"」とします。
「@input=""」は、入力欄に変更があった場合に発生するイベントです。
「($event.target as HTMLInputElement).value」は、入力欄の値です。
「emit('update:modelValue', 値)」は、親コンポーネントにイベントを発生します。
prop 名が指定されている場合は、「emit('update:prop名', 値)」とします。
src/App.vue
実行結果

コード
<script setup lang="ts">
// 受け取るプロパティの宣言
const props = defineProps<{
modelValue: string
}>()
// 発行するイベントの宣言
const emit = defineEmits<{
(e: 'update:modelValue', value: string): void
}>();
</script>
<template>
<!-- @input: 1文字入力するたびに発生するイベント -->
<!-- emit('update:modelValue', 新しい値)。親に値を更新するように通知する -->
<input type="text" :value="props.modelValue" @input="emit('update:modelValue', ($event.target as HTMLInputElement).value)" />
</template>
「:value="props.modelValue"」は、親コンポーネントの v-model で指定された値を片方向バインディングで入力欄に反映します。modelValue は、v-model で prop 名を指定しなかった場合のデフォルトの名前です。
prop 名は「v-model:title」のように「v-model:prop名」の形で指定します。
この場合、子コンポーネントでは「:value="props.title"」とします。
「@input=""」は、入力欄に変更があった場合に発生するイベントです。
「($event.target as HTMLInputElement).value」は、入力欄の値です。
「emit('update:modelValue', 値)」は、親コンポーネントにイベントを発生します。
prop 名が指定されている場合は、「emit('update:prop名', 値)」とします。
src/App.vue
コード
<script setup lang="ts">
import { ref } from 'vue';
import MyInput from './components/MyInput.vue';
const value = ref("");
</script>
<template>
<MyInput v-model="value" /><br /><br />
<button @click="value = ''">クリア</button><br /><br />
{{ value }}
</template>
実行結果

4. サンプル3 - (新)独自コンポーネントで双方向バインディング
src/components/MyInput.vue
コード
<script setup lang="ts">
const modelValue = defineModel('modelValue');
</script>
<template>
<input v-model="modelValue" type="text" />
</template>
defineModel() を使用すると、サンプル2の defineProps、defineEmits、@input が不要になります。
