Vue.js の基本 (6)

これまで何度も Vue はリアクティブだリアクティブだと書いてきました。

上記は ON/OFF のラジオボタンを選択することで、テキストボックスの有効/無効が切り替わります。
これは isOn というデータにもとづいてリアクティブに行われています。

ところで、データが変更されたときに何らかの処理を行いたい場合はどうなるでしょうか? 普通は、データが変更されたということを現在の値と新しい値を持って調べなければならないかと思いますが、これはなかなか辛い処理です。

リアクティブ的でない処理の場合は、以下のようになるかと思います。

きっかけ発生(何らかの操作など) → データ変更有無の確認 → 処理実行  

これが自然な場合は問題ありません。ボタンをクリックしたときにデータを送信する、などは当然そうなるでしょう。
では以下のケースはどうでしょうか。

データαが更新されたら何らかの処理を行いたい
イベントA → データαを更新する(しないこともある)
イベントB → データαを更新する(しないこともある)
イベントC → データαを更新する(しないこともある)

イベントA、B、C それぞれで処理の呼び出しを行うか、あるいは データαが何らかのHTML要素にひもづいたデータであれば、change イベントをハンドリングするという手があります。しかしそうでない場合はその手は使えません。
そしていずれの方法でも、データαの値が更新されたかどうかを調べる必要があります。データαがスカラ値でなかった場合は、さらに面倒なことになるでしょう。

Vue では、データ変更を検出するにはウォッチャを使用することができます。

この例では、ボタンが2つあり、どちらのボタンもデータの値をインクリメントしますが、データの値が10以上になると alert を表示するというものです。

JavaScript のコードを見ると、data や methods の並びに watch というキーがあります。これがウォッチャの定義です。
ウォッチャには、ウォッチするデータの名前をキーに指定して、それが変更されたときに実行する処理を関数として与えます。
ウォッチャの処理には、変更後の値、変更前の値が引数として渡ってきます。
上記の例では、その関数の中で値が10以上になったかをチェックして alert を出しています。

ここでウォッチャは、何によって値が変更されたのかについて関知していないというところがポイントです。

普通は、共通化したとしてもこうなるでしょう。

inc1: function() {
  this.value += 1;
  alertByValue(); // value を見て alert を表示する処理
},

この場合、inc1 は値によって alert を出すということと結びついてしまっています。
もし3つ目のボタンが増えたり、他の処理で value が変更するようになった場合、それらでも共通の関数を呼び出すようにしなければなりません。

しかし Vue であれば、データによってそれらが切り離されます。

inc1 ----> value <---- value のウォッチャ
// inc1 は value を変更するだけ その先で何が起こるかは知らない
// value のウォッチャは value を見て処理を行うだけ 誰が value を変更したのかは知らない