【Vue】v-bindとv-onとv-modelの関係【基本】

# 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インスタンスのプロパティによって束縛する役割があります。
文章だとわかりにくいのでサンプルプログラムです。

```html:template
<template>
  <div id="app">
    <input type="text" v-bind:value="myName">
  </div>
</template>
```

```js:Vueインスタンス
export default {
  name: 'App',
  data() {
    return {
      myName: 'MouMou'
    }
  }
}
```
inputタグのvalue属性の前に`v-bind:`がついています。そのあとに`="myName"`がついています。
これは***value属性の値を「Vueインスタンスのdataプロパティの`myName`」によって束縛します。***という意味です。
dataプロパティの`myName`の値が変更すると`v-bind:value`の値も`myName`に依存して変更されます。
ただし逆は成り立ちません。図にすると以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205371/fe924aeb-ff60-c8e6-d9bb-14eb42c09f19.png)
dataプロパティの`myName`の値を「太郎」にすると、テキストボックスの中身(= value)は「太郎」になりますが、
テキストボックスの中身(= value)を「太郎」にしても、dataプロパティの`myName`の値は「太郎」になりません。
***`v-bind`：Vueインスタンス内のデータ→html属性　の単方向のみ***

## 1-2.`v-on`について
`v-onは`イベントのサブスクリプションを行います。
サブスクリプションとはイベントの起動を監視して、イベント発火時に指定したプログラムの実行を行う機能です。
サンプルプログラムは以下です。

```html:template
<template>
  <div id="app">
    <input type="text" v-on:input="inputEvent">
  </div>
</template>
```

```js:Vueインスタンス
export default {
  name: 'App',
  methods:{
    inputEvent(event) {
      console.log(event.target.value);
    }
  }
}
```

inputタグ内に`v-on:input="inputEvent"`があります。
これは、***テキストボックスに文字がinputされたらinputEventメソッドを起動する。***という意味です。
なお、inputEventメソッドに引数があります。こうすることでDOMイベントを渡すことが可能です。
(`event.target.value`はテキストボックスに入った値を受け取ります。)
こちらも図にすると以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205371/4c5405d1-3eaa-ddb8-f3af-9058205d5925.png)
methodsプロパティからhtml属性にアクセスできませんが、
イベント（html属性）が発火することでmethodsプロパティのメソッドを実行することはできます。
***`v-on`：html属性(イベント)→Vueインスタンス内のデータ　の単方向のみ***

## 1-3. `v-model`について
`v-model`は双方向のデータバインディングを行います。
***`v-model=`で定義された変数と、Vueインスタンスのデータプロパティの変数を紐づけ、
どちらかが変わるともう一方も変わる***挙動をします。

```html:template
<template>
  <div id="app">
    <input type="text" v-model="myName">
    {{myName}}
  </div>
</template>
```
```js:Vueインスタンス
export default {
  name: 'App',
  data() {
    return {
      myName: 'MouMou'
    }
  }
}
```
`<input type="text">`の場合、
`v-model`は`value`属性のバインディングと`input`イベントのサブスクリプション両方の働きをしていることがわかります。
図にすると以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205371/5043dbd0-cd69-6382-6544-30149af1b21e.png)

# 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`の組み合わせで実現すると以下になります。

```html:template
<template>
  <div id="app">
    <input type="text" v-bind:value="myName" v-on:input="changeMyName">
    {{myName}}
  </div>
</template>
```

```js:Vueインスタンス
export default {
  name: 'App',
  data() {
    return {
      myName: 'MouMou'
    }
  },
  methods:{
    changeMyName(event) {
      this.myName = event.target.value;
    }
  }
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205371/55375a60-ed3b-5c71-67d1-fac77406e604.png)


1-3の`v-model`のサンプルと比べて冗長でわかりにくいですが、同じ挙動をします。
`v-model`を使用することで、双方向のバインディングがすっきりかけて、わかりやすくなりますね。

なお、[Vue公式サイト](https://v3.ja.vuejs.org/guide/forms.html#%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA%E4%BD%BF%E3%81%84%E6%96%B9)には以下のような記載があります
>内部的には、v-modelは異なる input 要素に対し異なるプロパティを使用し、異なるイベントを送出します。

>text および textarea 要素には、valueプロパティとinputイベントを用います
>チェックボックスおよびラジオボタンには、checkedプロパティとchangeイベントを用います
>select フィールドには、valueプロパティとchangeイベントを用います

# 3. まとめ
* `v-model` は `v-bind` と `v-on`で実現できる

最後まで読んでいただきありがとうございました！

## 参考
https://v3.ja.vuejs.org/guide/forms.html