0. はじめに
本記事は、Vueのディレクティブであるv-bindとv-onとv-modelの役割と関係を整理することが目標です。
今回の説明で出てくるプログラムはVue CLIの<template>, <script>内に書くことを想定しています。
1. v-bindとv-onとv-modelの関係
1-1. v-bindについて
v-bindは htmlの属性をVueインスタンスのプロパティによって束縛する役割があります。
文章だとわかりにくいのでサンプルプログラムです。
<template>
<div id="app">
<input type="text" v-bind:value="myName">
</div>
</template>
export default {
name: 'App',
data() {
return {
myName: 'MouMou'
}
}
}
inputタグのvalue属性の前にv-bind:がついています。そのあとに="myName"がついています。
これは***value属性の値を「VueインスタンスのdataプロパティのmyName」によって束縛します。***という意味です。
dataプロパティのmyNameの値が変更するとv-bind:valueの値もmyNameに依存して変更されます。
ただし逆は成り立ちません。図にすると以下のようになります。

dataプロパティのmyNameの値を「太郎」にすると、テキストボックスの中身(= value)は「太郎」になりますが、
テキストボックスの中身(= value)を「太郎」にしても、dataプロパティのmyNameの値は「太郎」になりません。
v-bind:Vueインスタンス内のデータ→html属性 の単方向のみ
1-2.v-onについて
v-onはイベントのサブスクリプションを行います。
サブスクリプションとはイベントの起動を監視して、イベント発火時に指定したプログラムの実行を行う機能です。
サンプルプログラムは以下です。
<template>
<div id="app">
<input type="text" v-on:input="inputEvent">
</div>
</template>
export default {
name: 'App',
methods:{
inputEvent(event) {
console.log(event.target.value);
}
}
}
inputタグ内にv-on:input="inputEvent"があります。
これは、***テキストボックスに文字がinputされたらinputEventメソッドを起動する。***という意味です。
なお、inputEventメソッドに引数があります。こうすることでDOMイベントを渡すことが可能です。
(event.target.valueはテキストボックスに入った値を受け取ります。)
こちらも図にすると以下のようになります。

methodsプロパティからhtml属性にアクセスできませんが、
イベント(html属性)が発火することでmethodsプロパティのメソッドを実行することはできます。
v-on:html属性(イベント)→Vueインスタンス内のデータ の単方向のみ
1-3. v-modelについて
v-modelは双方向のデータバインディングを行います。
v-model=で定義された変数と、Vueインスタンスのデータプロパティの変数を紐づけ、
どちらかが変わるともう一方も変わる挙動をします。
<template>
<div id="app">
<input type="text" v-model="myName">
{{myName}}
</div>
</template>
export default {
name: 'App',
data() {
return {
myName: 'MouMou'
}
}
}
<input type="text">の場合、
v-modelはvalue属性のバインディングとinputイベントのサブスクリプション両方の働きをしていることがわかります。
図にすると以下のようになります。

2. v-model = v-bind + v-on
v-model は v-bind と v-on の組み合わせで実現できます。
言い換えると、***v-modelは「v-bindとv-onの組み合わせの省略記法」***とも言えますね。
1-3のv-modelサンプルをv-bindとv-onの組み合わせで実現すると以下になります。
<template>
<div id="app">
<input type="text" v-bind:value="myName" v-on:input="changeMyName">
{{myName}}
</div>
</template>
export default {
name: 'App',
data() {
return {
myName: 'MouMou'
}
},
methods:{
changeMyName(event) {
this.myName = event.target.value;
}
}
}
1-3のv-modelのサンプルと比べて冗長でわかりにくいですが、同じ挙動をします。
v-modelを使用することで、双方向のバインディングがすっきりかけて、わかりやすくなりますね。
なお、Vue公式サイトには以下のような記載があります
内部的には、v-modelは異なる input 要素に対し異なるプロパティを使用し、異なるイベントを送出します。
text および textarea 要素には、valueプロパティとinputイベントを用います
チェックボックスおよびラジオボタンには、checkedプロパティとchangeイベントを用います
select フィールドには、valueプロパティとchangeイベントを用います
3. まとめ
-
v-modelはv-bindとv-onで実現できる
最後まで読んでいただきありがとうございました!
参考
