Vue3 deep watcher(ディープウォッチャー)に詰まったので備忘録


はじめに

こんにちは!
業務上でvueのwatchを利用して監視させようと思ったら、なぜか監視してくれなかったのでその備忘録になります。
個人的にはドキュメントがわかりにくく、解決するのに苦労しました。

同様に悩まれている方の少しでも助けになれたらと思います。

ではいきましょう。

ウォッチャとは

まずはwatchオプションについてです。
公式から抜粋したものが下記になります。

ほとんどの場合、算出プロパティの方が適切ですが、カスタムウォッチャが必要な場合もあります。そのため Vue は、データの変更に反応するためのより汎用的な方法を、watch オプションによって提供しています。これはデータを変更するのに応じて非同期処理や重い処理を実行したい場合に最も便利です。

引用元:vue.js公式ドキュメントより

要は、watchで監視対象のデータを指定してあげて、
そのデータに何かしらの変更が加えられたときに予め用意されていた関数を実行するオプションになります。

個人的に、超便利なんで算出プロパティより多用してしまっています・・・

参考の書き方は以下になります。

公式ドキュメントより
<script>
  const watchExampleVM = Vue.createApp({
    data() {
      return {
        question: '',
        answer: 'Questions usually contain a question mark. ;-)'
      }
    },
    watch: {
      // question が変わるたびに、この関数が実行される
      question(newQuestion, oldQuestion) {
        if (newQuestion.indexOf('?') > -1) {
          this.getAnswer()
        }
      }
    },
    methods: {
      getAnswer() {
        this.answer = 'Thinking...'
        axios
          .get('https://yesno.wtf/api')
          .then(response => {
            this.answer = response.data.answer
          })
          .catch(error => {
            this.answer = 'Error! Could not reach the API. ' + error
          })
      }
    }
  }).mount('#watch-example')
</script>

watchで指定している questionに変更が加えられるたびにwatchで登録している関数が実行される仕組みになっています。

deep watcherについて

上記の説明でwatchの使い方はなんとなくわかったと思います。
ただ、watchで監視対象がオブジェクトの場合、特殊な宣言を入れなければならない点に注意してください。

それが、deep(それとhandler)を追加することです。

dataをオブジェクトに変更した場合の処理を記述します。

<script>
  const watchExampleVM = Vue.createApp({
    data() {
      return {
        books: [
            { id: 1, title: '坊っちゃん' },
            { id: 2, title: '人間失格' },
            { id: 3, title: 'ノルウェイの森' }
        ],
      }
    },
    watch: {
      books: {
        handler: function ()  //handlerプロパティ内に処理を記述
             console.log("変更")
         },
         deep: true   //deepをtrueへ変更
       }
     },
  }).mount('#watch-example')

上記のように、handler内に監視対象が変更された際実行したい処理を記述し、
deepをtrueに変更すればオブジェクトでも監視対象となります。

最後に

これでまた一歩前進しましたね!