jQueryからVue.jsへ乗り換えてみた

## はじめに
　この記事でQiitaデビュー？ですが、文書書くの下手くそなので、読みにくかったらすみません。
JavaScriptとjQueryで個人的に作りたかったマネーカウンター（コインカウンター）を題材に、仕事と趣味半々で作ってました。でも複雑怪奇になったのでVue.jsを使えば多分楽になると思って、移植しました。
　なお、PWAとして [まねかん](https://horornis.com/mc/) と、 Cordovaでラッピングして [Androidアプリ「まねかん」](https://play.google.com/store/apps/details?id=com.horornis.money_can) がありますので、参考まで。 ソースは [GitHub](https://github.com/mishikawa-Horornis/money_can_web) においてあります。

## 「まねかん」制作のアイデア
　個人的にとある集会の会計をやっていて、小銭勘定を常に行う必要があったので、Excelで計算してたのですが、必ず手元にExcelがあるわけがないので、スマホアプリを作ろうと考えました。大元のExcelはこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359920/aee21e69-3d7f-8816-744e-4ef756ce8a39.png)
　ただし、スマホアプリを一から設計するだけの余裕と技量が無いので、Webアプリの作り方をググっていくと、`PWA`とか便利な技術があることに気づきました。`これならできる`と早速作成を開始しました。

## jQueryの頃
　考え方は単純なので、感覚としては

```html
<!DOCTYPE html>
<html lang="jp">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
     <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
</head>
<body>
<p>
    <span>1円：</span>
    <input class="count" type="number" value="0">
　　 <span class="subtotal s1">0円</span>
</p>
<p>
    <span>5円：</span>
    <input class="count" type="number" value="0">
    <span class="subtotal s5">0円</span>
</p>
<p>
    <span>10円：</span>
    <input class="count" type="number" value="0">
    <span class="subtotal s10">0円</span>
</p>
<p>
    <span>50円：</span>
    <input class="count" type="number" value="0">
    <span class="subtotal s50">0円</span>
</p>
<p>
    <span>100円：</span>
    <input class="count" type="number" value="0">
    <span class="subtotal s100">0円</span>
</p>
<p>
    <span>500円：</span>
    <input class="count" type="number" value="0">
    <span class="subtotal s500">0円</span>
</p>
<p>
    <span>千円：</span>
    <input class="count" type="number" value="0">
    <span class="subtotal s1000">0円</span>
</p>
<p>
    <span>弐千円：</span>
    <input class="count" type="number" value="0">
    <span class="subtotal s2000">0円</span>
</p>
<p>
    <span>五千円：</span>
    <input class="count" type="number" value="0">
    <span class="subtotal s5000">0円</span>
</p>
<p>
    <span>壱万円：</span>
    <input class="count" type="number" value="0">
    <span class="subtotal s10000">0円</span>
</p>
<p>
    <span class="total">0円</span>
</p>
<script>
    let items = [
        {type: 's1', callName: '1円', unit: 1},
        {type: 's5', callName: '5円', unit: 5},
        {type: 's10', callName: '10円', unit: 10},
        {type: 's50', callName: '50円', unit: 50},
        {type: 's100', callName: '100円', unit: 100},
        {type: 's500', callName: '500円', unit: 500},
        {type: 's1000', callName: '千円', unit: 1000},
        {type: 's2000', callName: '弐千円', unit: 2000},
        {type: 's5000', callName: '五千円', unit: 5000},
        {type: 's10000', callName: '壱万円', unit: 10000}
    ];
    $(function() {
        $('input').on('change', function () {
            let total = 0;
            for (let i = 0; i < $('.count').length; i++) {
                let c = Number($('input').eq(i).val());
                let u = items[i].unit;
                let subtotal = u * c;
                total += subtotal;
                $('.subtotal.' + items[i].type).text(`${Number(subtotal).toLocaleString()}円`);
            }
            $('.total').text(`合計：${Number(total).toLocaleString()}円`);
        });
    });
</script>
</body>
</html>
```

とデータを用意して、あとはinputタグだけで計算させてました。
あとはjQueryでイベント拾って計算させるだけという簡素な物でしたが、いろんなjQueryコンポーネントで装飾していくと、いろいろイベント処理とかが複雑になってきました。で、`Vue.js`をつかうと楽になる的な情報を聞きました。

## Vue.jsに移植
　Vue.jsは設計思想的には非常に合理的で、`フォームの値が変わったら計算項目はすべて自動計算される`のが特徴です。jQueryだとDOMにイベントを割り当てて、関数を定義しなければいけませんが、基本の書き方をすれば、全部計算してくれます。

```html
<!DOCTYPE html>
<html lang="jp">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
    <p v-for="(item, index) in items">
        <span>{{ item.callName }}</span><input type="number" v-model.number="item.counts"><span class="subtotal"> {{ subtotalMoney[index] }} 円</span>
    </p>
    <p>
        <span>合計： {{ totalMoney }} </span>
    </p>
</div>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            items: [
                {callName: '1円', unit: 1, counts: 0},
                {callName: '5円', unit: 5, counts: 0},
                {callName: '10円', unit: 10, counts: 0},
                {callName: '50円', unit: 50, counts: 0},
                {callName: '100円', unit: 100, counts: 0},
                {callName: '500円', unit: 500, counts: 0},
                {callName: '千円', unit: 1000, counts: 0},
                {callName: '弐千円', unit: 2000, counts: 0},
                {callName: '五千円', unit: 5000, counts: 0},
                {callName: '壱万円', unit: 10000, counts: 0}
            ]
        },
        computed: {
            totalMoney: function () {
                let total = 0;
                for (let i = 0; i < this.items.length; i++) {
                    total += this.items[i].unit * this.items[i].counts;
                }
                return Number(total).toLocaleString();
            },
            subtotalMoney: function () {
                let subtotals = [];
                for (let i = 0; i < this.items.length; i++) {
                    subtotals.push(Number(this.items[i].unit * 
                        this.items[i].counts).toLocaleString());
                }
                return subtotals;
            }
        }
    });
</script>
</body>
</html>
```

　Vue.jsは見た目に難しいようですが意外と単純で、`computed:`節に計算する関数を書けば、いちいち関数をコールする必要もありません。
　jQueryだけだとイベントを一つ一つ書かなければいけませんが、すっきりします。

## 雑感
　何で先に Vue.js を覚えなかったのか？と思うほど動作を単純化できます。もちろん見栄えを良くするにはBootstrapとかで装飾したりでjQueryも必要ですけれども…
　そのうちVueコンポーネントの書き方でも書こうかなと思ってます。
　続き：[Vue.jsのコンポーネントの作り方（たぶん初級編）](https://qiita.com/mishikawa-Horornis/items/0094d176f0e80f2c4ae4)

## 参考

Vue.js 公式サイト（日本語） https://jp.vuejs.org/index.html
jQuery 公式サイト（英語） http://jquery.com/