I have a watcher
on a deep nested object. I am using Vue.set()
to add a reactive property to the object. This is triggering the watcher but the both the newVal and oldVal console logs are showing the data with the new property added to it already rather than the oldVal showing what it was prior to adding the new property to it.
<button @click="addData">Add</button>
data() {
return {
myData: {
time: {
}
}
}
},
watch: {
myData: {
handler(newVal, oldVal) {
console.log("NEW", newVal);
console.log("OLD", oldVal);
},
deep: true
}
},
methods: {
addData() {
this.$set(this.myData.time, 'other','testing')
}
}
As mentioned by @Terry, vue doesnt keep a referency to the oldValue
, see what the docs says:
Note: when mutating (rather than replacing) an Object or an Array, the old value will be the same as new value because they reference the same Object/Array. Vue doesn’t keep a copy of the pre-mutate value.
There is some ways you can solve that:
Using vanilla javascript
JSON string
.JSON.parse
on your Watch
function to convert the string back to a object.data() {
return {
myData: {
time: {
}
}
}
},
computed: {
computedMyData() {
return JSON.stringify(this.myData);
}
},
watch: {
computedMyData: {
handler(newValJSON, oldValJSON) {
let newVal = JSON.parse(newValJSON),
oldVal = JSON.parse(oldValJSON);
console.log("NEW", newVal);
console.log("OLD", oldVal);
},
deep: true
}
},
methods: {
addData() {
this.$set(this.myData.time, 'other','testing')
}
}
Fiddle: https://jsfiddle.net/mLbuf6t0/
Using LODASH
cloneDeep
function.data() {
return {
myData: {
time: {
}
}
}
},
computed: {
computedMyData() {
return _.cloneDeep(this.myData)
}
},
watch: {
computedMyData: {
handler(newVal, oldVal) {
console.log("NEW", newVal);
console.log("OLD", oldVal);
},
deep: true
}
},
methods: {
addData() {
this.$set(this.myData.time, 'other','testing')
}
}
Fiddle: https://jsfiddle.net/mLbuf6t0/2/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With