【vue】 computedで自動で再計算する

算術プロパティと呼ばれる機能です。dataが固定の値を出力するのに対し、computedは計算した値を出力するというものです。書き方はmethodと似ていますが、役目はそれと違います。

computedを利用した例

例えば、次の例を見てみましょう。

const app = Vue.createApp({
    data() {
        return {
            shareId: "abcde",
            shareUrl: "https://example.com/"
        }
    },
    mounted() {
        this.createShareUrl();
    },
    methods: {
        startShare() {
            this.shareId = "abcde"; // TODO: ランダムで変更する処理
            this.createShareUrl();
        },
        changeShareId() {
            this.shareId = "bcdef"; // TODO: ランダムで変更する処理
            this.createShareUrl();
        },
        stopShare() {
            this.shareId = "";
            this.createShareUrl();
        },
        createShareUrl() {
            this.shareUrl = "https://example.com/?id=" + this.shareId;
        }
    }
});

シェア用のURLを生成する機能を作っているようですが、何度もcreateShareUrlを呼び出しています。その上、urlは表示以外で使うとは思えません。 (内部はidで管理のため)

こういった、特定の値が変わると自動で更新してほしい値は、その値に連動して自動的に表示が書き換わるのが理想ですよね。しかし表示だけだった場合にHTML側で連結したりするのは、ロジックをHTMLに書いていることになるのであまり良くありません。そこで、computedの出番です。

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 = "";
        }
    }
});

スッキリしました。computedにメソッドが入っているのがわかります。

computedの特徴

  • 利用している変数の値が変更されると, 自動的にcomputedも再計算される
  • dataと同様の方法で値を取得できる
  • 直接書き換えることは、追加実装しないとできない
    • this.shareUrl = "aaa"のようなことはsetterを実装しないとできない

という特徴があります。なにかの値に応じて、計算した結果を表示したいときに便利です。

値を取得する

methodsとは違い、関数としてではなく、dataと同様に変数のように呼び出します。

const app = Vue.createApp({
    data() {
        return {
            shareId: "abcde",
        }
    },
    computed: {
        shareUrl() {
            return "https://example.com/?id=" + this.shareId;
        }
    }
});
<p>{{ shareUrl }}</p>

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

vue内でも、普通の変数のように呼び出しますが、取得のみで代入はしません。

const app = Vue.createApp({
    data() {
      return {
        shareId: "abcde",
      }
    },
    computed: {
        shareUrl() {
            return "https://example.com/?id=" + this.shareId;
        }
    },
    methods: {
        changeShareId() {
            this.shareId = Math.random().toString(32).substring(2);

            // computedのメソッドは変数のように呼び出す (この時点で更新済み)
            console.log(this.shareUrl);
        },
    }
});

setterも実装はできるのでsetできなくはないですが面倒です。methodswatchが向いている場面がほとんどです。

リアクティブ性

上の動作例では、computedに使用している変数が更新されると、自動で対応するcomputedに設定したメソッドが動作し、HTML側の表示が更新されます。

つまり、値を更新した後にわざわざ更新する処理の呼び出しを書かなくてよいということです。

ここで、使用している値がリアクティブなものでない場合は、値が変わっていたとしても更新されません。

ここで該当するリアクティブなものとは、vueのdataで設定した値が主です。

const app = Vue.createApp({
    data() {
      return {
        shareId: "abcde",
      }
    },
    computed: {
        date() {
            // new Date()の結果は時刻によって変わるが、リアクティブではないのでcomputed実行の条件を満たさない
            return new Date();
        },
        shareUrl() {
            // dataにいれたshareIdの値が更新されると、shareUrl()は実行される
            return "https://example.com/?id=" + this.shareId;
        }
    },
    methods: {
        // ...
    }
});

setterの実装

通常は値を取得するgetterのみですが、値をセットするsetterも作ることができます。

const app = Vue.createApp({
    data() {
        return {
            firstName: "Taro",
            lastName: "Yamada"
        };
    },
    computed: {
        fullName: {
            get: function () {
                return `${this.firstName} ${this.lastName}`;
            },
            set: function (v) {
                const names = v.split(" ");
                this.firstName = names[0];
                this.lastName = names[names.length - 1];
            }
        }
    }
});

上のスクリプトの例では、fullNameに値を代入した際にfullNamesetが呼ばれます。

つまり、vueでthis.fullName = "Hoge Fugaaa"をしたり、

<input type="text" v-model="fullName">

で反映したりするとsetが実行されます。引数には代入しようとしている値が入ります。

これはJavascriptでよく見られるgetterとsetterの書き方です。

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

methodsとの違い

比較してみましょう. methodcomputedの主な違いは2点です.

computedmethods
実行タイミング内部で利用している値が変更されたとき呼び出したとき
呼び出し方dataと同じメソッド呼び出しと同じ

つまり、普通にロジックを実装するならmethods、利用する値が変更されたときに自動的に計算したい、かつ戻り値を使いたいならcomputedを利用すると良いです。dataの代わりとして使えます。

利用する値が変更されたときに自動的にロジックを走らせたい、でも戻り値は不要という場合は、後で紹介するwatchが適任です。

また、computedは裏で結果がキャッシュされているため、余分な再計算が起こらないのもメリットです。

まとめ

computedは、中で使用する値が更新されると自動で再計算し、表示する値を更新できるものです。methodとの違いを把握して使い分けられるようになりましょう。

似ているwatchについては下の記事にあります。

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

vue computed thumb

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