プロパティをまとめて監視したかったのでオブジェクトを用意して監視していたのですが、表題のところでつまづきました。
解決したので備忘録です。
watchのおさらい
index.html
<div id="app">
<input type="text" v-model="num">
</div>
<script>
new Vue({
el: '#app',
data: {
num: 0,
},
watch: {
num: {
handler: function(to, from) {
console.log(from + ' -> ' + to);
}
},
},
})
</script>
numを監視して、変更前と変更後をconsoleに吐き出す簡単なアプリケーションです。
ここまではなんの問題もなく動きます。
オブジェクトを監視するとうまく動かない
index.html
<div id="app">
<input type="text" v-model="obj.num">
</div>
<script>
new Vue({
el: '#app',
data: {
obj: {
num: 0,
}
},
watch: {
obj: {
deep: true, // オブジェクト内のプロパティを監視対象に含めるためdeepをtrueに
handler: function(to, from) {
console.log(from.num + ' -> ' + to.num);
}
},
},
})
</script>
上記のように記述した場合、obj.numを変更してもconsoleには変更前と変更後に同じ値が出力されてしまいました。
シャローコピーされた値が帰ってきているためこのような現象になるのだと思います。
算出プロパティを監視して解決
index.html
<div id="app">
<input type="text" v-model="obj.num">
</div>
<script>
new Vue({
el: '#app',
data: {
obj: {
num: 0,
}
},
computed: {
computedObj: function() {
return Object.assign({}, this.obj); // ディープコピーしたものを返す
},
},
watch: {
computedObj: { // 算出プロパティを監視
deep: true,
handler: function(to, from) {
console.log(from.num + ' -> ' + to.num);
}
},
},
})
</script>
ディープコピーした値を返す算出プロパティを用意し、その算出プロパティを監視するようにしました。
fromとtoは別参照のオブジェクトになったため無事正しいオブジェクトが帰ってきました。