基礎からメモ: Vue.js CH4-p128 ウォッチャーの使い方
コンポーネントのwatch
オプションに、監視するデータの名前と、変化した時に呼び出されるハンドラ関数を定義する。新旧データ比較のために、ハンドラの引数として第一引数に「新い値」、第二引数に「古い値」を受け取れる。
基本的な構文はこんな感じ。
var app = new Vue({ el: '#app', data: { ................................ }, watch: { 監視するデータ: function(新しい値, 古い値) { // value が変化した時に行いたい処理 }, 'item.value': function(newVal, oldVal) { // オブジェクトのプロパティも監視できる。 } } })
ウォッチャーのオプション
プロパティ | 値 | 説明 |
---|---|---|
deep | Boolean | ネストされたオブジェクトも監視する |
immediate | Boolean | 初期読み込み時にも呼び出す |
これらのオプションを使うには、監視するデータ名をキーとするオブジェクトにまとめる必要がある。その場合のハンドラーはhandler
プロパティに定義する。
var app = new Vue({ el: '#app', data: { ................................ }, watch: { list: { handler: function(newVal, oldVal) { // list が変化した時に行いたい処理 }, deep: true, immediate: true } } })
deep
オプションが有効な場合、例えば配列要素内のプロパティが更新されたときにも呼び出される。
this.list[0].name = "NewValue!"
インスタンスメソッドにウォッチャーを登録する
this.$watch
を使うことで、インスタンスメソッドにウォッチャーを登録することができる。
created: function() { this.$watch('value', function(newVal, oldVal) { // .................. }) }
インスタンスメソッドの場合は、watch
オプションでの登録とは少し書き方が違い、引数に次の情報を渡す。
[
監視するデータ,
ハンドラ,
オプションオブジェクト // 任意
]
例:createdフックでウォッチャーを登録する場合
created: function() { this.$watch('value', function() { // .................. }, { immediate: true }) }
ウォッチャーの解除
インスタンスメソッドで登録した場合は、戻り値を使って監視の解除が可能。
var unwatch = this.$watch('value', handler) unwatch() // valueの監視を解除
この仕組みを使って、一度だけ動作するウォッチャーを定義できる。
var unwatch = this.$watch('list', function() { // listが編集されたことを記録する this.edited = true // 監視を解除 unwatch() }, { deep: true })
実行頻度の制御
フォーム入力などで監視対象の値が高頻度で変化する場合、非同期通信などのコストの高い処理を呼び出すとパフォーマンスが低下する。
setTimeout
やLodash
ライブラリなどを使って、ウォッチャーの実行頻度を制御できる。
debounce
はLodash
のメソッド。実行から指定ミリ秒後にコールバックを呼び出す。
watch: { value: _.debounce(function(newVal) { // コストの高い処理 }, // valueの変化が終わるのを待つ時間をミリ秒指定 500 ) }
複数の値を監視する
width
またはheight
が変化した時など複数の値を監視する場合、インスタンスメソッドを使って監視対象のデータをそれら複数の値を返す関数にして登録する。
this.$watch(function() { return [this.width, this.height] }, function() { // width または height が変化した場合の処理 })
この監視対象を返す関数の部分を算出プロパティにすることで、よりすっきりと合理的に記述できる。
computed: { watchTarget: function() { return [this.width, this.height] } }, watch: { watchTarget: function() { ...... } }
フォームを監視してAPIからデータを取得する
フォームのセレクタで文字列(Vue.js 又は jQuery)が選ばれると、その変化に応じてGitHubのAPIからトピックのリポジトリを検索する例。
<body> <div id="app"> <!-- フォームを監視してAPIからデータを取得する --> <select v-model="current"> <option v-for="topic in topics" v-bind:value="topic.value"> {{ topic.name }} </option> </select> <div v-for="item in list">{{ item.full_name }}</div> <pre>{{ $data }}</pre> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script> <script src="main.js"></script> </body>
[main.js]
var app = new Vue({ el: '#app', data: { list: [], current: '', topics: [ { value: 'vue', name: 'Vue.js'}, { value: 'jQuery', name: 'jQuery'} ] }, watch: { current: function(val) { // GitHubのAPIからトピックのリポジトリを検索 axios.get('https://api.github.com/search/repositories', { params: { q: 'topic:' + val } }).then(function(response) { this.list = response.data.items }.bind(this)) } }, })