jQueryを使うならpetite-vueを使ってほしい。

私がまだWeb初心者で(今でも実戦経験はありませんが)、`Vue`さえ知らない頃はよく`jQuery`のお世話になりました。

しかし、今では`jQuery`を使うことは一切ありません。

なぜなら、`jQuery`を使用したい場面では必ず`petite-vue`を使用したほうが良いと思っているからです。

そこで、**私の独断と偏見による**`jQuery` **VS** `petite-vue` を開催することにしました。

# 私の独断と偏見による`jQuery` VS `petite-vue`

ということで、**掛け算M*NをBase-Bでリアクティブに表示するプログラム**を書いてきました。

## jQuery

<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="xxmoqBW" data-user="ajiken4610" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ajiken4610/pen/xxmoqBW">
  jQuery test</a> by ajiken4610 (<a href="https://codepen.io/ajiken4610">@ajiken4610</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

```html:jquery.html
<h1>Multiply
  <input class="x-input" value="10" style="vertical-align:middle;font-size:2rem;width:5rem;text-align:right;"/><sub class="base"></sub>x
  <input class="y-input" value="10" style="vertical-align:middle;font-size:2rem;width:5rem;text-align:right;"/><sub class="base"></sub>in BASE
  <input class="base-input" value="10" style="vertical-align:middle;font-size:2rem;width:5rem;text-align:right;"/><sub>(10)</sub>
</h1>
<div style="overflow-x: auto">
  <table class="table" style="text-align:right;border-collapse:collapse;" border="1"></table>
</div>
<script src="https://unpkg.com/jquery@3.7.1/dist/jquery.min.js"></script>
<script>
  const xInput = $('.x-input');
  const yInput = $('.y-input');
  const baseInput = $('.base-input');
  const baseSub = $('.base');
  const table = $('.table');
  const toUpperString = (s, b) => s.toString(b).toUpperCase();
  const updateGUI = () => {
    const base = parseInt(baseInput.val());
    const x = parseInt(xInput.val(), base);
    const y = parseInt(yInput.val(), base);
    baseSub.text(`(${base})`);
    table.empty();
    const thead = $('<thead></thead>');
    table.append(thead);
    const theadtr = $('<tr style="border-bottom: 2px solid"></tr>');
    thead.append(theadtr);
    const theadtrtd0 = $('<td style="border-right:2px solid;width: 1.5rem">x</td>');
    theadtr.append(theadtrtd0);
    for (var i = 0; i < x + 1; i++) {
      const theadtrtdn = $(`<td style="width: 1.5rem">${toUpperString(i, base)}</td>`);
      theadtr.append(theadtrtdn);
    }
    const tbody = $('<tbody></tbody>');
    table.append(tbody);
    for (var i = 0; i < y + 1; i++) {
      const tbodytrm = $('<tr></tr>');
      tbody.append(tbodytrm);
      const tbodytrmtd0 = $(`<td style="border-right:2px solid">${toUpperString(i, base)}</td>`);
      tbodytrm.append(tbodytrmtd0);
      for (var j = 0; j < x + 1; j++) {
        const tbodytrmtdn = $(`<td>${toUpperString(i * j, base)}</td>`);
        tbodytrm.append(tbodytrmtdn);
      }
    }
  };
  xInput.change(updateGUI);
  yInput.change(updateGUI);
  baseInput.change(updateGUI);
  updateGUI();
</script>
```

## petite-vue

<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="NWeZdQo" data-user="ajiken4610" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ajiken4610/pen/NWeZdQo">
  petite-vue inline-test</a> by ajiken4610 (<a href="https://codepen.io/ajiken4610">@ajiken4610</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

```html:petite-vue.html
<script src="https://unpkg.com/petite-vue" defer="defer" init="init"></script>
<style>
  [v-cloak] {
    display: none;
  }
</style>
<div v-cloak="v-cloak" v-scope="{}">
  <div v-scope="{x:null, y:null, xString:'10', yString:'10', base:10}">
    <h1>Multiply
      <input v-model="xString" style="vertical-align:middle;font-size:2rem;width:5rem;text-align:right;" v-effect="x = parseInt(xString, base)"/><sub>({{ base }})</sub>x
      <input v-model="yString" style="vertical-align:middle;font-size:2rem;width:5rem;text-align:right;" v-effect="y = parseInt(yString, base)"/><sub>({{ base }})</sub>in BASE
      <input v-model.number="base" style="vertical-align:middle;font-size:2rem;width:5rem;text-align:right;"/><sub>(10)</sub>
    </h1>
    <div style="overflow-x:auto;" v-scope="{toUpperString:(s,b) =&gt; s.toString(b).toUpperCase()}">
      <table style="text-align:right;border-collapse:collapse;" border="1">
        <thead>
          <tr style="border-bottom:2px solid;">
            <td style="border-right:2px solid;width:1.5rem;">x</td>
            <td v-for="i in x + 1" style="width:1.5rem;">{{ toUpperString(i - 1, base) }}</td>
          </tr>
        </thead>
        <tbody>
          <tr v-for="i in y + 1">
            <td style="border-right:2px solid;">{{ toUpperString(i - 1, base) }}</td>
            <td v-for="j in x + 1">{{ toUpperString((i - 1) * (j - 1), base) }}</td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</div>
```

## 比較

## 挙動の違い
`jQuery`の`change`イベントと、`petite-vue`の`v-model`が発火されるタイミングが違います。

- `jQuery`
  `<input>`から`blur`したタイミングで`change`イベントが発火する。
- `petite-vue`
  `<input>`の`input`イベントが呼ばれたタイミングで`v-model`が発火する。
  (IMEを使う言語では`input`イベントではなく変換が確定されたタイミングで呼ばれる)

私の勝手な推測ですが、`jQuery`を使用する場面ってだいたいフォームだと思うので、`jQuery`の挙動で十分だと思います。

`petite-vue`は少しリアクティブすぎる感じがありますね。

`jQuery`が一本先取しました。

## 実行速度
これは上のCodepenをいじってもらえばすぐ分かります。**明らかに`jQuery`の方が早いです。**

あれれ、おかしいな。思ったより`petite-vue`って大したことないんじゃね。

この勝負、`jQuery`の勝ち(価値)を認めざるを得ないのでは？？

## ソースコードの長さ
`Pug`で記述したため、その長さを比べます。
### 行数
#### `jQuery`: 64行
#### `petite-vue`: 43行
行数だけ見れば、`petite-vue`のほうが短く書けることがわかります。

### 文字数
[スペース込み、スペース無視]
#### `jQuery`: [2073,1712]
#### `petite-vue`: [1497,1105]
文字数を見ても、`petite-vue`が短いです。

### 1行当たりの文字数(スペースを除く)
#### `jQuery`: 26.75
#### `petite-vue`: 25.70
これは大差ありませんでした。
#### 1行の長さは変わりませんが、`petite-vue`の方が短く書けるようです。

## Minifyしたソースコードのサイズ
私は`Pug`で記述しましたが、Minifyした`HTML`のサイズで測ります。
#### `jQuery`: 1881 bytes
#### `petite-vue`: 1165 bytes
`petite-vue`の方がかなり小さい！
これは`petite-vue`の勝ちといってよいでしょう。

## バンドルサイズ
重要なのはこちらです。

ライブラリの大きさを合計したサイズ、`バンドルサイズ`は自分が書いたプログラムのサイズよりページの読み込み速度に関係するといえます。(特に小さいサイトでは。)

- `jquery.min.js` ([unpkg](https://unpkg.com/jquery@3.7.1/dist/jquery.min.js))は、87533 bytesです。
- `petite-vue.iife.js` ([unpkg](https://unpkg.com/petite-vue@0.4.1/dist/petite-vue.iife.js))は、16901 bytesです。

これに、自分のソースの大きさを合計すると、

- `jQuery`: 89414 bytes
- `petite-vue`: 18066 bytes

`petite-vue`の方が圧倒的に小さいことわかります。

これに関しても、`petite-vue`が優位に立つようです。

## 可読性
可読性に関しては、Vueベースである`petite-vue`が良いのは当たり前だと思っていますが、議論の余地はあります。
具体的にどのような点が可読といえるか、少し言語化してみました。

### 関心の分離[^1]

まず最初に言っておきます。**関心の分離は重要ではありません。**
これには比較対象があります。**プログラムが疎結合であること**と比べて、です。

プログラムが疎結合であることは、プログラムの可読性を上げると私は信じています。

具体的に今回の例で言えば、
- `jQuery`では、JavaScriptは`<script>`に完全に分離されています。
  これにより、関心が分離されます。
- `petite-vue`では、JavaScriptはそれぞれのDOMに書かれています。
  これにより、実行するとどのような結果が得られるかが視覚的に理解できます。

どちらが重要であるかは言うまでもないでしょう。

### 関数ベースか、コンポーネントベースか。
これに関しては、どちらが良いということはないと思います。

例えば`React`は関数ベースですが、`Vue.js`と可読性に関しては変わりません。

私が、コンポーネントベースの記述に慣れすぎているだけです。

# 結論
よっぽど動的に変化するサイトでない限りは、`petite-vue`を使うべきです。
何よりも、可読性が高くなります。可読性が高いことのメリットは計り知れません。
以上を持ちまして、**私の独断と偏見による**`jQuery` **VS** `petite-vue`を終戦とさせていただきます。

# Tips
驚くべき事実があります。
`petite-vue`では物足りなく、`Vue.js`を使いたいと思っているあなたに朗報です。
`jQuery`の大きさは、86KB[^2]で、`Vue.js`のランタイムの大きさは84KB[^3]です。

バンドルサイズだけ見れば、ランタイムのみの`Vue.js`のほうが小さいことがわかります。ぜひ`.vue`ファイルをコンパイルして持ち運んであげてください。

[^1]: https://ja.vuejs.org/guide/scaling-up/sfc.html#what-about-separation-of-concerns
[^2]: https://unpkg.com/jquery@3.7.1/dist/jquery.min.js
[^3]: https://unpkg.com/vue@3.3.4/dist/vue.runtime.global.prod.js