Help us understand the problem. What is going on with this article?

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

以下3つのオプションの区別が曖昧だったので、メモしておきます。
ソースコードは公式サイトよりお借りしました。

computedオプション

  • 算出プロパティ
  • リアクティブな依存関係にもとづきキャッシュされる
  • リアクティブな依存関係が更新されたときにだけ再評価されるので、逆に言えばリアクティブな依存がない場合は二度と更新されない
  • ゲッター(getter関数)とセッター(setter関数)の両方が利用できる(デフォルトはゲッターのみ)

ゲッターとセッター

computedでセッターを使用した場合、dataオプションで設定されたプロパティを更新することもできます。

ゲッターとセッターの定義

ゲッター

特定のプロパティ値を取得するためのメソッド

セッター

特定のプロパティ値を設定するためのメソッド

ソースコード

firstNameプロパティやlastNameプロパティを変更すると再描画が起こりますが、nowプロパティはリアクティブな依存関係にないため、最初に読み込まれた以降は変化しません。

vue_test01.html
<!DOCTYPE>
<head>
  <meta charset="UTF-8">
  <title>Vue.js_test01</title>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
  <div id="app">
    <input v-model="firstName" placeholder="firstName">
    <input v-model="lastName" placeholder="lastName">
    <p>firstName: {{ firstName }}</p>
    <p>lastName: {{ lastName }}</p>
    <p>fullName: {{ fullName }}</p>
    <p>now: {{ now }}</p>
  </div>

  <script>
      var vm = new Vue({
          el: '#app',
          data: {
              firstName: '',
              lastName: ''
          },
          computed: {
              // fullName/now: 算出プロパティ名
              fullName: function () {
                  return this.firstName + ' ' + this.lastName
              },
              now: function () {
                  return Date.now()
              }
          }
      })
  </script>
</body>

methodsオプション

  • メソッド
  • 再描画が起きると常に関数を実行する

ソースコード

firstNameプロパティやlastNameプロパティを変更すると再描画が起こるので、それに合わせてnowプロパティも変化します。

vue_test01.html
<!DOCTYPE>
<head>
  <meta charset="UTF-8">
  <title>Vue.js_test01</title>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
  <div id="app">
    <input v-model="firstName" placeholder="firstName">
    <input v-model="lastName" placeholder="lastName">
    <p>firstName: {{ firstName }}</p>
    <p>lastName: {{ lastName }}</p>
    <p>fullName: {{ fullName() }}</p>
    <p>now: {{ now() }}</p>
  </div>

  <script>
      var vm = new Vue({
          el: '#app',
          data: {
              firstName: '',
              lastName: ''
          },
          methods: {
              fullName: function () {
                  return this.firstName + ' ' + this.lastName
              },
              now: function () {
                  return Date.now()
              }
          }
      })
  </script>
</body>

watchオプション

  • 監視プロパティ
  • 既にセットされているプロパティを監視する
  • 監視するプロパティの名前と、そのプロパティに変化(トリガー)があった場合に実行する関数(ハンドラ)を対にして指定する
  • 関数は、更新後・更新前のプロパティの値を引数に取ることができる
  • 処理は実行するが、データは返さない
  • computedでは行えないコストの高い処理を実行できる

以下、公式サイトより。

この場合では、watch オプションを利用することで、非同期処理( API のアクセス)の実行や、処理をどのくらいの頻度で実行するかを制御したり、最終的な answer が取得できるまでは中間の状態にしておく、といったことが可能になっています。これらはいずれも算出プロパティでは実現できません。

ソースコード

fullNameプロパティの表示はwatchオプションで描画することもできますが、逆に冗長なコードになってしまいます。

vue_test01.html
<!DOCTYPE>
<head>
  <meta charset="UTF-8">
  <title>Vue.js_test01</title>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
  <div id="app">
    <input v-model="firstName" placeholder="firstName">
    <input v-model="lastName" placeholder="lastName">
    <p>firstName: {{ firstName }}</p>
    <p>lastName: {{ lastName }}</p>
    <p>fullName: {{ fullName }}</p>
    <p>now: {{ now }}</p>
  </div>

  <script>
      var vm = new Vue({
          el: '#app',
          data: {
              firstName: '',
              lastName: '',
              // プロパティはあらかじめセットしておく
              fullName: '',
              now: '',
          },
          watch: {
              // firstName/lastName/now: 監視対象のプロパティ名
              // newValue: 更新後のプロパティの値
              // oldValue: 更新前のプロパティの値
              firstName: function (newValue, oldValue) {
                  console.log(newValue, oldValue);
                  this.fullName = newValue + ' ' + this.lastName
              },
              lastName: function (newValue, oldValue) {
                  console.log(newValue, oldValue);
                  this.fullName = this.firstName + ' ' + newValue
              },
              // 監視しているが、値に変化がないので変更されることはない
              now: function () {
                  return Date.now()
              }
          }
      })
  </script>
</body>

参考サイト

リアクティブの探求
【Vue.js】v-modelを使ってた時になんか動なかったお話
算出プロパティとウォッチャ

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away