【Vue.js】v-modelの仕組みを完全理解|双方向バインディングの裏側とカスタム実装

【Vue.js】v-modelの仕組みを完全理解|双方向バインディングの裏側とカスタム実装 Vue.js

v-modelはVue.jsでフォーム要素を操作する際に欠かせないディレクティブですが、その裏側の動作やカスタム実装について深く理解できているでしょうか?

この記事では、v-modelの基本構造から、内部でどのようにデータの同期が行われているのかを解説し、さらにカスタムコンポーネントでv-modelを使用する方法も紹介します。

v-modelの基本構造

v-modelは、フォーム要素とデータの「双方向バインディング」を簡単に記述できる構文糖衣です。

<input v-model="message" />

上記は実際には以下の2つの処理を自動的に行っています:

  1. value属性へのバインド
  2. inputイベントによるデータ更新
<input
  :value="message"
  @input="message = $event.target.value"
/>

つまり、v-modelは「:value」と「@input」を省略形としてまとめてくれている機能だということです。

v-modelの仕組みとイベント

v-modelが利用するイベントはフォーム要素によって異なります:

  • input要素 → inputイベント
  • checkboxradiochangeイベント
  • selectchangeイベント

Vueはこれらを適切に処理し、指定されたデータプロパティと同期させています。

v-modelと修飾子

v-modelには、データの扱いを細かく制御するための修飾子があります。

  • .lazy:inputイベントではなくchangeイベントで同期
  • .number:文字列入力を数値に自動変換
  • .trim:前後の空白を自動で除去
<input v-model.lazy="name" />
<input v-model.number="age" />
<input v-model.trim="keyword" />

カスタムコンポーネントでのv-modelの使用

v-modelはネイティブ要素だけでなく、自作コンポーネントでも使用可能です。その場合、以下のルールに従って動作します:

  1. modelValue という props を受け取る
  2. update:modelValue イベントを emit する

カスタムコンポーネントの例

// MyInput.vue
<template>
  <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />
</template>

<script>
export default {
  props: ['modelValue']
}
</script>

このコンポーネントを親で次のように使えます:

<MyInput v-model="myText" />

v-modelのエイリアス指定(複数バインディング)

Vue 3では、v-modelにエイリアスを指定することで、複数のv-modelバインディングを持つことができます。

<MyComponent v-model:title="title" v-model:content="content" />

この場合、コンポーネント側では以下のように対応する必要があります:


props: {
  title: String,
  content: String
},
emits: ['update:title', 'update:content']

まとめ

v-modelはVueのデータバインディングを直感的に扱える便利な機能ですが、その実体は「propsとイベントのやり取り」によって成り立っています。

自作コンポーネントでv-modelを使う際には、modelValueとupdate:modelValueのペアを理解することが重要です。Vue 3ではより柔軟なバインディングが可能となっているため、場面に応じてエイリアスの活用も検討しましょう。

v-modelの仕組みを正しく理解することで、より可読性と拡張性の高いコンポーネント設計が可能になります。