VueJS 速習チュートリアル

Vue ウォッチャ (Watchers)

ウォッチャ(Watcher) は、監視対象の データプロパティ(Data Property) と同じ名前を持つメソッドです。
ウォッチャは、そのデータプロパティの値が変更されるたびに実行されます。
特定のデータプロパティの値が変化した際に、何らかのアクション(処理)が必要な場合にウォッチャを使用します。

1. ウォッチャのコンセプト

ウォッチャは、Vue インスタンス において私たちが学習する4番目の設定オプションです。これまでに datamethodscomputed の3つを見てきました。
これらと同様に、ウォッチャにも Vue インスタンス内での予約名として watch が用意されています。

1.1 シンタックス (Syntax)

const app = Vue.createApp({
  data() {
    return {
      // データの定義
    }
  },
  watch: {
    // ウォッチャの定義
  },
  computed: {
    // 算出プロパティの定義
  },
  methods: {
    // メソッドの定義
  }
})

ウォッチャは、同じ名前のデータプロパティを監視します。
私たちはウォッチャメソッドを明示的に呼び出すことはありません。プロパティの値が変更されたときにのみ、自動的に呼び出されます。
ウォッチャメソッドでは、新しい値(New Value)古い値(Old Value) の両方を入力引数として利用できます。

1.2 実装例:入力値の制限(バリデーション)

<input type="range"> 要素を使用して rangeVal の値を変更します。ウォッチャを使用して、ユーザーが「不正」とみなされる 20 から 60 の間の値を選択できないように制御する例です。

<div id="app">
  <input type="range" v-model="rangeVal">
  <p>現在の値: {{ rangeVal }}</p>
</div>

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
  const app = Vue.createApp({
    data() {
      return {
        rangeVal: 70
      }
    },
    watch: {
      // rangeVal プロパティを監視
      rangeVal(val) {
        if( val > 20 && val < 60 ) {
          if(val < 40) {
            this.rangeVal = 20;
          }
          else {
            this.rangeVal = 60;
          }
        }
      }
    }
  })
  app.mount('#app')
</script>

2. 新しい値と古い値を利用するウォッチャ

ウォッチャメソッドでは、プロパティの新しい値に加えて、変更前の値も自動的に入力引数として受け取ることができます。

2.1 実装例:座標の差分計算

<div> 要素のクリックイベントで、マウスポインタの X 座標(xPos)を記録します。ウォッチャは、新旧の引数を利用して、新しい X 座標と前の座標のピクセル差分を計算します。

<div id="app">
  <div v-on:click="updatePos" style="width:200px;height:100px;background-color:lightgray;">
    ここをクリック
  </div>
  <p>直前のクリックとの差分(xDiff): {{ xDiff }} px</p>
</div>

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
  const app = Vue.createApp({
    data() {
      return {
        xPos: 0,
        xDiff: 0
      }
    },
    watch: {
      // (新しい値, 古い値) の順で受け取る
      xPos(newVal, oldVal) {
        this.xDiff = newVal - oldVal
      }
    },
    methods: {
      updatePos(evt) {
        this.xPos = evt.offsetX
      }
    }
  })
  app.mount('#app')
</script>

2.2 実装例:メールアドレスのリアルタイム・フィードバック

新旧の値を使用して、入力が「無効」から「有効」に切り替わった瞬間にユーザーへフィードバックを返す例です。ここでは @ 記号が含まれているかどうかで簡易的に判定します。

<div id="app">
  <p>メールアドレスを入力してください:</p>
  <input type="email" v-model="inpAddress">
  <p v-bind:class="myClass">{{ feedbackText }}</p>
</div>

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
  const app = Vue.createApp({
    data() {
      return {
        inpAddress: '',
        feedbackText: '',
        myClass: 'invalid'
      }
    },
    watch: {
      inpAddress(newVal, oldVal) {
        if( !newVal.includes('@') ) {
          this.feedbackText = 'メールアドレスが有効ではありません';
          this.myClass = 'invalid';
        }
        else if( !oldVal.includes('@') && newVal.includes('@') ) {
          // 前の値に @ がなく、新しい値にある=今有効になった瞬間
          this.feedbackText = '完璧です!修正されました!';
          this.myClass = 'valid';
        }
        else {
          this.feedbackText = 'メールアドレスは有効です :)';
        }
      }
    }
  })
  app.mount('#app')
</script>

3. ウォッチャ vs. メソッド

どちらもファンクションとして記述されますが、多くの違いがあります。

項目メソッド (Methods)ウォッチャ (Watchers)
呼び出し元HTML から呼び出されるHTML からは参照されない
実行トリガー主にイベント(click等)が発生した時監視対象のデータが変更された時
自動引数デフォルトでイベントオブジェクトを受け取る自動的に「新しい値」と「古い値」を受け取る
任意の引数任意の値を引数として送ることができる他の値を引数として送ることはできない
実行タイミング明示的な呼び出しが必要データの変更を検知して自動で実行される

4. ウォッチャ vs. 算出プロパティ

ウォッチャと算出プロパティ(Computed Properties)は、どちらもファンクションとして記述され、依存関係が変更されたときに自動的に呼び出されます。HTML から直接呼び出されることはありません。

主な違いは以下の通りです:

  • 依存関係の数:
    • ウォッチャ は、監視するように設定された「1つのプロパティ」のみに依存します。
    • 算出プロパティ は、複数のプロパティに依存することができます。
  • 役割と使用方法:
    • 算出プロパティ はデータプロパティと同様に扱われ、動的な値を生成するために使用されます。
    • ウォッチャ は HTML から参照されず、データの変更に伴う副作用(API呼び出し、ログ出力、複雑なバリデーションなど)を実行するために使用されます。