2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2021-05-27

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

目的の処理

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

画面収録-2021-05-27-10.24.11.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
目的の処理とは違う挙動になってしまいました....

間違いの原因

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

公式ドキュメントによると、v-modelは入力された値の形式にかかわらず文字列として返して性質があるようです。

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

return 2 + 3 + 7

というような処理をしたかったのに実際は、

return "2" + "3" + "7"

このような処理になってしまったということです。

解決策

公式ドキュメントを参考に以下のように修正します。

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

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

結論

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

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

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

参考サイト

2
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?