【vue】 watchを使って値の変化時に自動で処理を実行する

監視プロパティとも呼ばれます。computedと似ており、監視している値に変更があれば自動的に実行されるものです。

しかし、watchではcomputedよりもロジックの処理に重点が置かれています。

watchを用いた例

次のような例を見てみましょう。

const app = Vue.createApp({
    data() {
        return {
            shareId: "abcde",
        }
    },
    computed: {
        shareUrl() {
            return "https://example.com/?id=" + this.shareId;
        }
    },
    methods: {
        startShare() {
            this.shareId = "abcde";
            this.sendShareData();
        },
        changeShareId() {
            // ランダム文字列を生成
            this.shareId = Math.random().toString(32).substring(2);
            this.sendShareData();
        },
        stopShare() {
            this.shareId = "";
            this.sendShareData();
        },
        sendShareData() {
            // サーバに新しいシェア情報を送信
            // ...
        }
    }
});

先程と似た例ですが、今度はデータを送信しているようです。中で値の代入などはするでしょうが、戻り値を使いたいということはなさそうです。

しかし、shareIdの変更がある場所全てにsendShareDataの呼び出しを付けるのは面倒ですし、保守性も下がります。

そこでwatchです。watchは指定した変数を監視して、変更があれば自動的に実行してくれるものです。

const app = Vue.createApp({
    data() {
        return {
            shareId: "abcde",
        }
    },
    computed: {
        shareUrl() {
            return "https://example.com/?id=" + this.shareId;
        }
    },
    methods: {
        startShare() {
            this.shareId = "abcde";
        },
        changeShareId() {
            // ランダム文字列を生成
            this.shareId = Math.random().toString(32).substring(2);
        },
        stopShare() {
            this.shareId = "";
        },
    },
    watch: {
        shareId(newVal, oldVal) {
            // サーバに新しいシェア情報を送信
            // ...
            console.log(newVal)
        },
    }
});

最後の方にwatchを追加しました。methodsと同様に複数設定できます。

watchの使い方

ここで、少し構造を見ていきましょう。

vueのwatchの書き方

構造の特徴として、名前が監視したい対象であるという点です。更新後の値だけで十分な場合、第2引数は省略できます。何なら更新後に呼ばれるので、引数は無しにして直接this.shareIdなどとしても良いです。

また、連想配列なので、次のように書くこともできます。

const app = Vue.createApp({
    // ...
    watch: {
        shareId: function (newVal, oldVal) {
            // ...
            console.log(newVal)
        },
    }
});

これであれば、キー名に使えない文字列が含まれていても"share-id": function ()...のようにかけますね。

オブジェクトの値を監視したい場合

"foo.bar.1"のように、配列に近い感覚で書きますが、[]ではなく.で指定します。

const app = Vue.createApp({
    data() {
        return {
            foo: {
                bar: [
                    10,
                    20,
                    30
                ]
            }
        }
    },
    watch: {
        // ここ
        "foo.bar.1": function () {
            console.log(this.foo.bar[1]);
        },
    }
});

いつもの変数の扱いと似ていますが、注意点として、配列のインデックスも.で指定します。[]で指定しても動作しないので注意です。インデックスはいつもどおり0から始まります。

また、オブジェクトや配列の中身が更新されたら、という条件にしたい場合は次のようにします。

{
    // ...
    watch: {
        "foo.bar": {
            handler: function () {
                console.log(this.foo.bar[1]);
            },
            deep: true, // オブジェクトの中まで監視する
        }
    }
}

このように書くと、foo.bar[0]foo.bar[1]foo.bar[2]どれに変更が入っても実行されます。

ちなみに、これまでに出した今までのwatchの書き方は省略した書き方です。省略せずに書くと、

{
    watch: {
        "監視対象": {
            handler: function () {
                // 実行したい処理
            },
            deep: false, // trueにすると、オブジェクトの中身全てが監視対象になる
            immediate: false // trueにすると、mountedより先に一度呼ばれる
        }
    }
}

となります。

immediatetrueの場合、beforeCreatecreatedの間に一度呼ばれます。これらはvueのライフサイクルで、mountedはその後に呼ばれます。

動作例

最後に、実際に動いている例を見てみましょう。IDを更新ボタンを押して1秒待つと、更新完了と表示されるプログラムです。

See the Pen by Totori (@souki202) on CodePen.

URLはcomputedで、1秒後に表示するのはwatchで行っています。

まとめ

監視プロパティ(watch)は、特定の値が更新されたのをトリガーにして、何かの処理を行いたい際に最適です。戻り値は取らないので、戻り値が必要な場合はmethodcomputedを推奨します。

似ているcomputedに関しては下の記事にあります。

method, computed, watchの使い分けは下の記事にあります。

vue watch thumb

役に立ったらシェアしよう!