【Vue.js】監視プロパティWatchの使い方やメリットを実例で解説|データの変更時に自動で処理を実行してくれる便利ツール(deepやimmediateオプション)

vue-js-prograshi(プロぐらし)-kv Vue.js
記事内に広告が含まれていることがあります。

Vue.jsには監視プロパティ(Watch)という機能があります。これを使うと、ブラウザ上のインプットタグなどでユーザーが何かを入力したり、データを変更したときに、変更を検知して自動で設定した処理を走らせることができます。

ここではwatchの使い方やdeepやimmediateオプションについて実例で解説しています。

(watchのことをウォッチャーとも呼びます。)


監視プロパティ(watch)の書き方

監視プロパティはVueインスタンスの中で次のように記述します。

watch:{監視するプロパティ名: function(新しい値用の変数, 古い値用の変数){処理}}

通常は見やすくするため改行して表示することが一般的です。以下は同じ記述です。

watch:{
  監視するプロパティ名: function(新しい値用の変数, 古い値用の変数){
    処理
  }
}


functionを省略した記述方法

上記は最も基本的なwatchの記述方法です。

ですがこの書き方以外にも、Vue.jsのmethodsやwatchなどのオブジェクトはfunctionを省略して記述することもできます

watchでfunctionを使わない場合は以下のようになります。

watch:{
  監視するプロパティ名( 新しい値用の変数, 古い値用の変数 ){
    処理
  }
}

: functionを省略することができます「:」も省略することに注意してください。

point

実際のプロジェクトなどでは、functionを記述せずに書くことが一般的です。



監視プロパティの実例

まずは、v-modelディレクティブを使って、Vue.js側とブラウザ(HTML)側の両方で双方向バインディングしたデータを作成します。

watchでそのデータを監視して、変更があった場合にconsole.logの処理を実行するプログラムを作成します。


Vue.jsのコード

Vueインスタンスの中に、データとしてプロパティ名hello、値「Hello World!」のデータを持たせます。

Watchオブジェクトの中で、上記のhelloプロパティを監視する設定にします。

helloプロパティのデータに変更があった場合、都度console.logを実行して、コンソールに元のhelloのデータと、変更後のhelloのデータを表示します。

var app = new Vue({
    el:"#app",
    data:{
        hello: 'Hello World!'
    },
    watch:{
        hello(newValue, oldValue){
            console.log('new:', newValue, 'old:', oldValue)
        }
    }  
})

なお、console.logは引数をカンマでつなぐことで、複数のデータをコンソールに出力することができます。

console.log('new:', newValue, 'old:', oldValue)の場合は出力は「”new:” “Hello Worl” “old:” “Hello World”」のようになります。


HTMLコード

HTMLファイルには次の3つの要素を表示させます。

  1. dataオブジェクトのhelloプロパティ自体を表示。
  2. インプットタグでhelloプロパティの値を変更可能にする(双方向バインディング)
  3. dataオブジェクト自体を表示。
<body>
    <div id="app">
        <p>
            {{ hello }}
        </p>
        <p>
            <input type="text" v-model:value="hello">
        </p>
        <pre>{{ $data }}</pre>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>

dataオブジェクトのhelloプロパティ自体を表示

dataオブジェクトのプロパティを表示するには開始タグと終了タグの間でマスタッシュ構文 {{ }} を使います。

{{ hello }}


インプットタグでhelloプロパティの値を変更可能にする(双方向バインディング)

Vueのデータとブラウザ上のデータを連動させるには、v-modelディレクティブを使います。

inputタグで表示されている値を双方向バインディングする場合は次のように、value属性に対してv-modelを適用し、値に結びつけるdataプロパティ名を記載します。

<input type="text" v-model:value="hello">

この設定で、デフォルトではhelloプロパティの値が表示され、変更するとVue.js側のhelloプロパティ自体のデータも書き換わるようになります。

双方向バインディングとは?

双方向バインディングとは、Vue.jsに記述したプロパティ(データ)をHTML上で呼び出し、かつ、HTML上でそのデータを編集できるようにすることです。

Vue.jsとHTMLが双方向でつながるため、双方向バインディングと呼びます。詳細は下記をご参考ください。

【Vue.js】v-modelとは何か?使い方や注意点を実例で解説|双方向データバインディングとは何か?


dataオブジェクト自体を表示

Vue.jsのdataオブジェクトのデータは$dataという変数に入っています。(Vue.jsの仕様です)

ブラウザにコードを直接表示する場合はpreタグを使用します。

<pre>{{ $data }}</pre>

以上で準備は完了です。


ブラウザとコンソールの表示

ブラウザとコンソールの状態は以下のようになります。

デフォルトはブラウザ上に「Hello World!」が表示され、コンソールには何も表示されていません。

 ↓ 「!」と「d」の2文字を削除

inputタグの「!」と「d」の2文字を削除すると、ブラウザとコンソールの表示が次のように変わります。

inputタグの状態に合わせて、helloプロパティの値も置き変わります。コンソールを見ると、変更があった回数だけwatchが起動して、console.logを実行していることがわかります。

※ 「!」を削除したのが1回目の変更、「d」を削除したのが2回目の変更です。

↓ 「こんにちは」に置き換えると次のようになります。


実例2:距離の相互変換プログラム

watchオブジェクトの理解をより深めるために、ブラウザで入力された数値に合わせて、変更が発生する毎にkm, m, mmを自動換算するプログラムを作成します。

inputタグを3つ用意し、どれか一つの入力内容を変更すると、watchが働き、他の2つも自動で変更されます。

作成手順

  1. 初期値0のdataオブジェクトを用意(.js)
  2. inputタグを用意(.html)
  3. v-modelで双方向バインディング(.html)
  4. watchプロパティをセット(.js)

▼完成形(ブラウザ表示)


Vue.jsのコード

var app = new Vue({
    el:"#app",
    // 1. 初期値0のdataオブジェクトを用意
    data:{
        km:0,
        m:0,
        mm:0
    },
    // 4. watchプロパティをセット
    watch:{
        km(value){
            this.km = value
            this.m = value*1000
            this.mm = value*1000000
        },
        m(value){
            this.km = value/1000
            this.m = value
            this.mm = value*1000
        },
        mm(value){
            this.km = value/1000000
            this.m = value/1000
            this.mm = value
        }
    }
})


HTMLファイルのコード

<body>
    <div id="app">
        <!-- 2. inputタグを用意(.html) -->
        <p>
            <!-- 3. v-modelで双方向バインディング(.html) -->
            <input type="text" v-model="km">km
        </p>
        <p>
        <input type="text" v-model="m">m
        </p>
        <p>
            <input type="text" v-model="mm">mm
        </p>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>

以上で完了です。


ブラウザでの表示

↓ mmに「1231」と入力

mmの数値を入力すると、mとkmも連動して自動計算した数値が入力されます。


実例3:フルネームを返すプログラム

watchオブジェトを使えば、ファーストネームとラストネームを入力すると、フルネームを自動計算して表示するプログラムを作成することができます。

Vue.jsのコード

var app = new Vue({
    el:"#app",
    data:{
        firstName:'',
        lastName:'',
        fullName:''
    },
    watch:{
        firstName(value){
            this.fullName = value + " " + this.lastName
        },
        lastName(value){
            this.fullName = this.lastName + " " + this.firstName
        }
    }
})


HTMLのコード

<body>
    <div id="app">
        <p>
            firstName: <input type="text" v-model:value="firstName">
        </p>
        <p>
            lastName: <input type="text" v-model:value="lastName">
        </p>
        <p>
            fullName: {{ fullName }}
        </p>

        <br>
        <pre>{{$data}}</pre>

    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>


ブラウザの表示

デフォルトでは空になっています。

 ↓ 名前を入力

入力されたデータに合わせて、フルネームを計算して表示します。


監視プロパティのオプション

監視プロパティにはオプションが用意されています。

watchの便利オプション
  1. deep
  2. immediate

deepはdataオブジェクトのネストしたデータも監視する設定です。deepがない場合は、設定したプロパティ自体の変更があった場合のみしかwatchは作動しません。

immidiateは画面の初期ロード時にもwatchの処理を実行するようにするオプションです。デフォルトは初回読み込み時は処理を実行せず、変更があった場合だけwatchが作動します。


オプションがある場合とない場合の書き方の違い

オプションを設定するときは、処理をhandlerプロパティの値にする必要があります。

watch:{
  監視するプロパティ名: function( 新しい値用の変数, 古い値用の変数 ){
    処理
  }
}
watch:{
  監視するプロパティ名:{
    handler: function( 新しい値用の変数, 古い値用の変数 ){
      処理
    },
   オプション名: 真偽値
  }
}
point

・処理をhandlerプロパティの値にする。
・handlerとオプション(deep, immediate)が並列になる。


functionの有無

なお、オプションありのwatchでも、オプションが無い場合と同様に、functionを省略して記述できます。

watch:{
  監視するプロパティ名: {
    handler( 新しい値用の変数, 古い値用の変数 ){
      処理
    },
   オプション名: 真偽値
  }
}

handlerの後ろの: functionを省略することができます「:」も省略することに注意してください。


deepオプションの使い方実例

trueの場合、ネストされたオブジェクトも監視する設定になります。

deep = true :ネストしたオブジェクトも監視する。
deep = false :ネストは監視しない。デフォルトの設定です。

deepオプションの実例

colorsプロパティをwatch対象にし、deep= trueのとき。colorsプロパティ配下のnameプロパティを変更したときに、console.logで変更有無を感知するプログラムを作成します。

var app1 = new Vue({
    el: '#app',
    data: {
        colors: [
            {name: 'Red'},
            {name: 'Green'},
            {name: 'Blue'}
        ]
    },
    //▼deepオプションありの監視プロパティ
    watch: {
        colors:{
            handler: function(newVal, oldVal){
                console.log('deepが適用されました!')
            },
            deep: true
        }
    }
})
<body>
    <div id="app">
        <ul>
            <li v-for="color in colors">
                {{ color.name }}   
            </li>
        </ul>
        <hr>
        <p>(確認用)dataオブジェクト</p>
        <pre>{{ $data }}</pre>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>


ブラウザとコンソールの表示

コンソール上でcolorsの{name: 'Blue'}のデータを変更すると次のようになります。

合わせて読みたい

コンソール上でVue.jsのデータを直接変更する方法の詳細については下記をご参照ください。

(参考)【Vue.js】ブラウザから直接プロパティやデータを簡単に変更する方法|テストで便利なテクニック


immediateオプションの使い方実例

immediateオプションを設定すると、初期読み込み時にも監視で指定した処理を実行します。デフォルトはfalseです。

immediate = ture: 初回読み込み時に監視プロパティの処理を実行。
immediate = false: 初回は実行しない。

(deepとの併用も可能です)

immediateオプションの実例

colorsプロパティをwatch対象にし、deep= trueのとき。colorsプロパティ配下のnameプロパティを変更したときに、console.logで変更有無を感知するプログラムを作成します。

immediate: trueにするため、ページ初回読み込み時にconsole.logが実行されるようになります。

colorsプロパティをwatch対象にし、deep= trueのとき。colorsプロパティ配下のnameプロパティを変更したときに、console.logで変更有無を感知するプログラムを作成します。

var app1 = new Vue({
    el: '#app',
    data: {
        colors: [
            {name: 'Red'},
            {name: 'Green'},
            {name: 'Blue'}
        ]
    },
    //▼deepオプションありの監視プロパティ
    watch: {
        colors:{
            handler: function(newVal, oldVal){
                console.log('deepが適用されました!')
            },
            deep: true,
            immediate: true
        }
    }
})
<body>
    <div id="app">
        <ul>
            <li v-for="color in colors">
                {{ color.name }}   
            </li>
        </ul>
        <hr>
        <p>(確認用)dataオブジェクト</p>
        <pre>{{ $data }}</pre>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>


ブラウザとコンソールの表示

ページをロードし、何も変更を加えていない時点で、watchに記述した処理が実行されていることがわかります。


タイトルとURLをコピーしました