Vue.jsで数値（number）が絡むフォーム入力バインディング（v-model）を行うときにハマったこと

Vue.jsで数値が絡むフォーム入力バインディングを行うときにハマったことについて解説していきます。

## 目的の処理

1. 数値を入力するフォーム（ `type="number"` ）を3つ作成
1. この3つのフォームに与えられた数値の合計を`total`としてフロントに反映

![画面収録-2021-05-27-10.24.11.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681937/f5a92ca9-0527-5988-cdc8-e480066446b8.gif)


この処理を行うためにVue.jsにあるフォーム入力バイディング（`v-model`）と算出プロパティ（`computed`）を使用していきます。

## 間違ったコード

```TotalCounter.vue
<template>
    <div>
        <div>
            <label for="first-num">First: </label> 
            <input type="number" name="first-num" v-model="firstNum">
        </div>
        <div>
            <label for="second-num">Second: </label>
            <input type="number" name="second-num" v-model="secondNum">
        </div>
        <div>
            <label for="third-num">Third: </label> 
            <input type="number" name="third-num" v-model="thirdNum">
        </div>
        <div>total: {{ totalNum }}</div>
    </div>
</template>

<script>
export default {

    data() {
        return {
            firstNum: 0,
            secondNum: 0,
            thirdNum: 0,
        }
    },

    computed: {
        totalNum() {
            return this.firstNum + this.secondNum + this.thirdNum
        }
    }
    
}
</script>
```

これは、実際に最初に書いたコードです。

初期値0の3つのデータ（`firstNum`, `secondNum`, `thirdNum`）を`v-model`を用いてフォームの入力の変更を反映、`compouted`でそれぞれの合計を`totalNum`として処理をするという内容になっています。

一見正しい記述内容に見えますが、これを確認してみると、以下のようになります。

![画面収録-2021-05-27-10.37.35.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681937/424f7fa8-d2cd-3914-aa89-c38e18677dba.gif)
目的の処理とは違う挙動になってしまいました....

## 間違いの原因

この間違った挙動は、`v-model`が返す値が要因となっています。

[公式ドキュメント](https://jp.vuejs.org/v2/guide/forms.html#number)によると、`v-model`は入力された値の形式にかかわらず文字列として返して性質があるようです。

今回の処理で説明すると、フォームの形式が`type="number"`になっているのにもかかわらず`v-model`で返ってくる値が文字列になってしまったために、`totalNum`内で、

```js
return 2 + 3 + 7
```
というような処理をしたかったのに実際は、

```js
return "2" + "3" + "7"
```
このような処理になってしまったということです。

## 解決策

[公式ドキュメント](https://jp.vuejs.org/v2/guide/forms.html#number)を参考に以下のように修正します。

```TotalCounter.vue
<template>
    <div>
        <div>
            <label for="first-num">First: </label> 
            <input type="number" name="first-num" v-model.number="firstNum">
        </div>
        <div>
            <label for="second-num">Second: </label>
            <input type="number" name="second-num" v-model.number="secondNum">
        </div>
        <div>
            <label for="third-num">Third: </label> 
            <input type="number" name="third-num" v-model.number="thirdNum">
        </div>
        <div>total: {{ totalNum }}</div>
    </div>
</template>

<script>
export default {

    data() {
        return {
            firstNum: 0,
            secondNum: 0,
            thirdNum: 0,
        }
    },

    computed: {
        totalNum() {
            return this.firstNum + this.secondNum + this.thirdNum
        }
    }
    
}
</script>
```

`v-model`に末尾に`.number`を追加することで、`v-model`は数値として値を返してくれるようになります。

![画面収録-2021-05-27-10.24.11.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681937/f5a92ca9-0527-5988-cdc8-e480066446b8.gif)

これで目的の処理になりました！

## 結論

Vue.jsの標準で搭載されている`v-model`はバイディングを行う際にとても便利な機能ですが、仕組みや使い方を間違ってしまうと、このような初歩的な部分でつまづいてしまいそうになりますね...

これからは、公式ドキュメントの参照を心がけます！

同じようなところでつまづいている方々の参考になれたならなと思います。

## 参考サイト

https://jp.vuejs.org/v2/guide/forms.html#number