【Vue.js】computedとwatchの使い分け

## はじめに
仕事で使う事になったので1からVue.jsについて学んだ（元々Angularでプロダクト開発をやっていた事はあるがAngularはだめか・・・）。
ちゃんと覚えておかないとまずそうな事を備忘録として1つ1つ残しておく。

## computedとwatchの使い分け
どちらも参照先の値（Vueインスタンスのdataプロパティの値）が更新された時に実行されるというのは同じだが、以下のように使い方に違いがある。

| # | 使い分け |
|:-:|---|---|
| computed | ・同期処理を実行する場合に使用（returnなので基本的には同期処理）<br>　※ただし頑張れば非同期的な処理もできる |
| watch | ・非同期処理を実行する場合に使用<br>・参照先の値を持つcomputedプロパティがHTML上に記載されていない時に使用 |

※ただし、参照先の値が変更された時に・・・という場面で何らかの処理を実行する際のBest Practiceは`computed`を用いる事。どうしても対応不可能な場合にのみ`watch`を利用するようにするのがポイント。

### 参照先の値を持つcomputedプロパティがHTML上に記載されていない時に使用　の例
「参照先の値を持つcomputedプロパティがHTML上に記載されていない時」とは、
Vueインスタンスのdataプロパティのある値が更新された時に何かを実行したいが、その値を依存関係に持つcomputedプロパティがHTML上に存在せず、それ(computed)が動作しないため、値が変更されても何も処理が実行できないといった場合の事。
![ezgif.com-gif-maker (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/382e2f67-3891-85be-96ca-066f2069cc1a.gif)
この動画で、

- Vueインスタンスのdataプロパティのある値

とは`counter`の事であり、この`counter`が変化した時に何かの処理を実行する事を想定して`console.log()`を実行している。
動画のソースコードは以下。

```html:sample.html
<body>
    <div id="app">
        <p>{{ counter }}</p>
        <button @click="counter += 1">+1</button>
        <!-- 参照先の値を持つcomputedプロパティがHTML上に記載されていない -->
        <!-- <p>{{ lessThanThree }}</p> -->
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
    <script>
        new Vue({
            el: '#app',
            data: {
                counter: 0
            },
            computed: {
                lessThanThree: function () {
                    console.log('computed');
                    return this.counter > 3 ? '3より上' : '3以下';
                }
            },
            watch: {
                counter: function () {
                    console.log('watch');
                }
            }
        })
    </script>
</body>
```

※上記のソースコードでは、Vueインスタンスに`lessThanThree`というcomputedプロパティが定義されているが、それがHTML上には記載されておらず（コメントアウトされており）computedが動作していない状態になっている。

### 同期・非同期　の例
![ezgif.com-gif-maker (4).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/9a187ddb-2722-19d9-d1b3-1672f7314f3d.gif)
この動画は、`counter`が変更された場合に`watch`が動き、変更の3秒後に`counter=0`にする処理を実行したもの。`computed`は同期で、`watch`は非同期でそれぞれ処理されている。
動画のソースコードは以下。

```sample.html
<body>
    <div id="app">
        <p>{{ counter }}</p>
        <button @click="counter += 1">+1</button>
        <p>{{ lessThanThree }}</p>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
    <script>
        new Vue({
            el: '#app',
            data: {
                counter: 0
            },
            computed: {
                lessThanThree: function () {
                    console.log('同期');
                    return this.counter > 3 ? '3より上' : '3以下';
                }
            },
            watch: {
                counter: function () {
                    const vm = this;
                    setTimeout(function () {
                        console.log('非同期');
                        vm.counter = 0;
                    }, 3000)
                }
            }
        })
    </script>
</body>
```

※上記で`const vm = this;`としている理由は[こちらを参照](https://developer.mozilla.org/ja/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#the_this_problem)

## Vue.jsの勉強メモ一覧記事へのリンク
Vue.jsについて勉強した際に書いた勉強メモ記事のリンクを集約した記事。

- https://qiita.com/yuta-katayama-23/items/dabefb59d16a83f1a1d4