Vue3 監視プロパティ

この章では、Vue3 の監視プロパティについて紹介します。watch私たちは watch を使用してwatchデータの変化に対応できます。

watchwatch の役割は、リアクティブプロパティの変化を監視し、プロパティが変更されたときに特定の操作を実行することです。これは Vue におけるリアクティブメカニズムの一種であり、データが変化したときに適切に対応し、カスタムロジックを実行することを可能にします。

watchこれにより、リアクティブプロパティの変化に対してより多くの制御と柔軟性が得られ、コンポーネントがデータの変化により適切に対応し、対応するロジックを実行できるようになります。

以下の例では、watch を使用してカウンターを実装しています:

例

<div id = "app">
    <p style = "font-size:25px;">カウンター: {{ counter }}</p>
    <button @click = "counter++" style = "font-size:25px;">クリック</button>
</div>
   
<script>
const app = {
  data() {
    return {
      counter: 1
    }
  }
}
vm = Vue.createApp(app).mount('#app')
vm.$watch('counter', function(nval, oval) {
    alert('カウンター値の変化 :' + oval + ' から ' + nval + '!');
});
</script>

試してみる »

以下の例では、キロメートルと米とメートルの間の換算:

例

<div id = "app">
キロメートル: <input type = "text" v-model = "kilometers"  @focus="currentlyActiveField = 'kilometers'">
    米 : <input type = "text" v-model = "meters" @focus="currentlyActiveField = 'meters'">
</div>
<p id="info"></p>    
<script>
const app = {
  data() {
    return {
      kilometers : 0,
      meters:0
    }
  },
  watch : {
    kilometers:function(newValue, oldValue) {
      // 現在の入力フィールドかどうかを判定
      if (this.currentlyActiveField === 'kilometers') {
        this.meters = newValue * 1000
      }
    },
    meters : function (newValue, oldValue) {
      // 現在の入力フィールドかどうかを判定
      if (this.currentlyActiveField === 'meters') {
        this.kilometers = newValue/ 1000;
      }
    }
  }
}
vm = Vue.createApp(app).mount('#app')
vm.$watch('kilometers', function (newValue, oldValue) {
  // このコールバックは vm.kilometers が変更された後に呼び出されます
  document.getElementById ("info").innerHTML = "変更前の値: " + oldValue + "、変更後の値: " + newValue;
})
</script>

試してみる »

「試してみる」ボタンをクリックしてオンラインの例を表示

上記のコードでは、2つの入力フィールドを作成しました。data プロパティでは、kilometers と meters の初期値はともに 0 です。watch オブジェクトは data オブジェクトの2つの監視メソッド(kilometers と meters)を作成しています。

入力フィールドにデータを入力すると、watch はリアルタイムでデータの変化を監視し、自身の値を変更します。以下のビデオデモをご覧ください:

非同期ロードでの watch の使用

非同期データのロードについて、Vue は watch オプションを通じて、データの変化に対応するためのより汎用的な方法を提供します。

以下の例では axios ライブラリを使用します。詳細は後で説明します。

例

<!--AJAX ライブラリや汎用ツールのエコシステムはすでにかなり豊富であるため、Vue のコアコードでは重複して-->
<!--これらの機能を提供せず、シンプルさを保っています。これにより、自分がより使い慣れたツールを自由に選ぶこともできます。-->
<script src="https://cdn.staticfile.org/axios/0.27.2/axios.min.js"></script>
<script src="https://cdn.staticfile.org/vue/3.2.37/vue.global.min.js"></script>
<script>
  const watchExampleVM = Vue.createApp({
    data() {
      return {
        question: '',
        answer: '各質問の最後に ? を入力する必要があります。'
      }
    },
    watch: {
      // 質問が変わるたびにこの関数が実行され、? で終わるようにします。中国語・英語の ? に対応
      question(newQuestion, oldQuestion) {
        if (newQuestion.indexOf('?') > -1 || newQuestion.indexOf('?') > -1) {
          this.getAnswer()
        }
      }
    },
    methods: {
      getAnswer() {
        this.answer = '読み込み中...'
        axios
          .get('/try/ajax/json_vuetest.php')
          .then(response => {
            this.answer = response.data.answer
          })
          .catch(error => {
            this.answer = 'エラー! API にアクセスできません。 ' + error
          })
      }
    }
  }).mount('#watch-example')
</script>

試してみる »

使い方のまとめ

watch は Vue 3 が提供するリアクティブなデータ監視メカニズムであり、単一または複数のプロパティを監視できます。

コールバック関数を渡すことでデータの変化を処理でき、ディープ監視や即時実行などのオプションをサポートしています。

1. 基本的な使い方

Vue 3 では、watch 関数はリアクティブプロパティを監視するために使用されます。

監視しているプロパティの値が変化すると、Vue はコールバック関数を実行します。

例

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0
    });

    watch(
      () => state.count, // 監視するプロパティ
      (newVal, oldVal) => { // 変化時のコールバック関数
        console.log(`count changed from ${oldVal} to ${newVal}`);
      }
    );

    return {
      state
    };
  }
};

2. 複数のリアクティブプロパティを監視する

複数のリアクティブプロパティを同時に監視したい場合は、配列を使用して複数の監視プロパティを渡すことができます:

例

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0,
      name: 'Vue3'
    });

    watch(
      [() => state.count, () => state.name], // 複数のプロパティを監視
      ([newCount, newName], [oldCount, oldName]) => {
        console.log(`count changed from ${oldCount} to ${newCount}`);
        console.log(`name changed from ${oldName} to ${newName}`);
      }
    );

    return {
      state
    };
  }
};

3. ディープ監視

監視対象がオブジェクトまたは配列で、その内部のネストされたプロパティも監視したい場合は、deepdeep: trueオプションを使用できます。これにより、オブジェクトのすべてのプロパティの変化が監視されます。

例

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      user: {
        name: 'Alice',
        age: 25
      }
    });

    watch(
      () => state.user, // オブジェクト全体を監視
      (newVal, oldVal) => {
        console.log('User object changed:', newVal, oldVal);
      },
      { deep: true } // ディープ監視を有効にする
    );

    return {
      state
    };
  }
};

4. 即時実行

デフォルトでは、watch は監視している値が変化したときのみコールバックをトリガーします。コンポーネントの読み込み時にコールバックを即時実行したい場合は、immediate オプションを設定できます。immediate: true。

例

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0
    });

    watch(
      () => state.count, // 監視するプロパティ
      (newVal, oldVal) => {
        console.log(`count changed from ${oldVal} to ${newVal}`);
      },
      { immediate: true } // 即時実行
    );

    return {
      state
    };
  }
};

5. 非同期操作

watch 内で非同期操作を実行する必要がある場合、コールバック関数内で async と await を直接使用できます。これにより、API リクエストやデータ保存などの操作を処理できます。

例

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0
    });

    watch(
      () => state.count,
      async (newVal, oldVal) => {
        console.log(`count changed from ${oldVal} to ${newVal}`);
        // 非同期リクエストを実行すると仮定
        await fetch(`https://api.example.com/count/${newVal}`);
      }
    );

    return {
      state
    };
  }
};

6. 複数のプロパティを監視し、handler 関数を使用する

watch を複数のプロパティを監視するためのハンドラとして使用することもできます。次のようになります:

例

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0,
      name: 'Vue3'
    });

    const handler = ([newCount, newName], [oldCount, oldName]) => {
      console.log(`count changed: ${oldCount} → ${newCount}`);
      console.log(`name changed: ${oldName} → ${newName}`);
    };

    watch([() => state.count, () => state.name], handler);

    return {
      state
    };
  }
};

7. watchEffect による簡略版の監視

Vue 3 には watchEffect API も用意されています。これは watch よりも簡潔で、具体的なデータソースを指定することなく、リアクティブデータの変化を自動的に追跡できます。

例

import { reactive, watchEffect } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0
    });

    watchEffect(() => {
      console.log(`count is: ${state.count}`);
    });

    return {
      state
    };
  }
};

watchEffect は自動的に countstate.countの変化を検出し、変化時にコールバックをトリガーします。

8. flush オプション

flush オプションは、watch のコールバック実行タイミングを制御するために使用されます。

デフォルトでは、watch のコールバックは DOM の更新後に実行されます。更新前にコールバックを実行する必要がある場合は、flush: 'pre' オプションを使用できます。flush: 'pre'。

例

import { reactive, watch } from 'vue';

export default {
  setup() {
    const state = reactive({
      count: 0
    });

    watch(
      () => state.count,
      (newVal, oldVal) => {
        console.log(`count changed from ${oldVal} to ${newVal}`);
      },
      { flush: 'pre' } // 更新前にコールバックを実行
    );

    return {
      state
    };
  }
};
その他の拡張