初心者向け　Vue.js　 v-model をなんとなく理解してみる

#はじめに
プログラミング初心者の方にとって、Qiitaのありがたい解説は、諸先輩方の技術レベルが高すぎて正直ついていけていないと思います:scream:

解説を理解しようにも、次から次に分からない言葉が出てきてググりまくっていませんか？ 

そこで、プログラミング初心者 (独学 3ヶ月) の小職が、Vue.jsの学習において初心者を挫折に追いやる難所をピックアップし、初心者ならではの少々強引な理解方法をご紹介したいと思います。(素人なら素人の分からないところが分かるはず！:thinking:)


今回は v-modelディレクティブの仕組みについて勉強します。

#対象者
* Vue.js を少しかじったことがある方
* ただなんとなく v-model を使っている方
* 独学で頑張っているけど、挫折しそうな方


#v-modelとは
[Vue.js 公式 フォーム入力バインディング](https://jp.vuejs.org/v2/guide/forms.html)

>form の input 要素 や textarea 要素、 select 要素に双方向 (two-way) データバインディングを作成するには、v-model ディレクティブを使用することができます。それは、自動的に入力要素のタイプに基づいて要素を更新するための正しい方法を選択します。ちょっと魔法のようですが、v-model はユーザーの入力イベントにおいてデータを更新するための基本的な糖衣構文 (syntax sugar) で、それに加えて、いくつかのエッジケースに対しては特別な配慮をしてくれます。

*ディレクティブ → 命令、指令
*バインディング → 結びつける

Vue.jsでフォームを作成する際は、v-modelにめちゃくちゃお世話になっていますよね？
初めてv-modelを使用した際は、何これ、エグいやん...:rolling_eyes:と思いました。

しかしながら、私と同じように、なぜ双方向のデータ結びつけが可能になるのか、理解しないままv-modelを乱用しまくっている初心者の方もいらっしゃいますよね？:sweat_smile:

#v-modelの正体
公式を確認すると以下の二つは同じであるということが分かります。

[Vue.js 公式 コンポーネントの基本](https://jp.vuejs.org/v2/guide/components.html)

```html
<input v-model="searchText">
```

```html
<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
>
```

v-modelは実は、v-bindとv-onの2つの処理を行っているということが分かりましたが、双方向データバインティングのイメージがいまいち理解できませんので、次章から深く掘り下げていきます。

#プロパティ → input要素 方向へのデータバインディング

まずは、v-bindについて学んでいきます。

[Vue.js 公式 クラスとスタイルのバインディング](https://jp.vuejs.org/v2/guide/class-and-style.html)

v-bindは、要素に、値を変更することができる属性を配置する命令を出します。

```vuejs
<input v-bind:value = "name">
```
つまり、上記の例では、input要素にvalue属性を配置し、そのvalue属性の値はnameプロパティによって変更することができるということです。
v-bindは省略することができるため、 :value と表記しても同じ意味です。

ここでinput要素のvalue属性について思い出してください。

```html
<input type="text" value="takunosuke">
```

input要素にvalue属性を指定すると、ブラウザで表示したときに初期値を設定することができましたよね？
上記の例では初期値として、takunosukeが入ります。

したがって、input要素において、v-bindでvalue属性を指定すると、プロパティの値を変更することによって、入力フォームの初期値を操ることができます:ok_hand:

ここで、名前を入力する簡単なフォームを作って動かしてみます。

![v-bind.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629856/d83062ec-8093-fa3a-f553-e1f3a68993b6.gif)


pタグにnameプロパティの値が入るようにコードを書きました。

nameプロパティの値を変更すると、v-bindしたvalue属性の値が変更され、inputフォームの初期値として表示されています。

したがって、 プロパティからinput要素方向へのデータのバインディングが可能となっていることが分かります!:thumbsup:

しかし、inputフォームに名前を入力しても下に名前が表示されないことから、input要素からプロパティ方向へのデータのバインディングはできていないことが分かります。

#input要素 → プロパティ 方向へのデータバインディング

続いて、v-onについて学んでいきます。

[Vue.js 公式 イベントハンドリング](https://jp.vuejs.org/v2/guide/events.html)

```vuejs
<input v-on:input = "name = $event.target.value">
```

v-onは、指定したイベントに対応して、処理を実行する命令を出します。
javascriptで勉強した、addEventListenerと同じものだと考えてください。
遊戯王でいうとトラップカードと同じものだと考えてください。

イベントは、ボタンクリックやマウスオーバーなどのユーザーによる挙動のことを指します。

上記の例では、 v-on:input となっておりますが、このinputはinputイベントのことを指しております。
v-onは@で代用することができるため、 @ input と表記しても同じ意味です。

inputイベントを確認してみましょう。

[input イベント MDN Web docs](https://developer.mozilla.org/ja/docs/Web/API/HTMLElement/input_event)

inputイベントは、input要素やtextarea要素のvalueが変更されたときに発動します。

また、 $event.targetとありますが、これによりイベントが発生した要素を取得することができます。

つまり、上記のコードは、input要素のvalueが変更されたら、nameプロパティにイベントが発生した要素(input)のvalueの値を代入せよ、という意味です:ok_hand:

ここで、実際に名前を入力する簡単なフォームを作って動かしてみます。
![v-on.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629856/6c84a4f3-751a-3a75-f91b-90ba666764df.gif)

pタグにnameプロパティの値が入るようにコードを書きました。

inputフォームに名前を入力すると同時に、inputイベントが発動し、nameプロパティにinputフォームに入力された名前が代入されているため、リアルタイムで反映されています。

したがって、 input要素からプロパティ方向へのデータのバインディングが可能となっていることが分かります!:thumbsup:

しかし、nameプロパティに名前を入力してもinputフォームに名前が表示されないことから、プロパティからinput要素方向へのデータのバインディングはできていないことが分かります。

#v-model 双方向 (two-way) データバインディング
上記2パターンのデータバインディングを組み合わせたものこそが、v-modelです。

では実際に2パターンを組み合わせ、v-modelを完成させてみます。

![v-model.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629856/1b817121-cd9d-f45e-1189-76a3f2d42890.gif)

このように双方向のデータバインディングが可能になっていることが分かります。

主に、v-modelはログインフォームや新規登録フォームの作成などで大活躍すると思いますが、その際に内部的にはこのようなことが起こっているということを意識していただければ幸いです。


#おわりに

以上、非常にざっくりな理解で大変恐縮ではございますが、締め括りとさせていただきます:sweat_smile:

v-modelとか意識せずに使えばいいじゃんと思ったそこの初心者の方、実は、このv-modelはinput要素やtextarea要素だけではなく、親子コンポーネント間のデータやり取りにも使用できるという衝撃の事実があるのです。したがって、本記事は次回への伏線となります:blush:

初心者の方々、今後も私と一緒に勉強していただければ幸いです。諸先輩方、いつもエラーが出るたびにお世話になっております。今後ともよろしくお願い申し上げます。

Mahalo
takunosuke