watch监听不到对象内部的变化
有的时候vue会出现这种现象,无法监听到复杂对象内部的变化:当对象里面原本有某一个属性,并对这个属性操作时,watch是可以监听到当前属性的变化的。但是,若对象里面本没有这个属性的时候,在操作时将属性添加进去,同时包括之后对这个属性的操作,watch是都检测不到的。
这是因为vue的watch会在初始化的时候通过object.defineProperty给对象的每一个属性都添加watcher来监听内部的变化。所以,后期添加上去的属性是无法检测到的。
解决方法:
如果想在初始化后添加一个属性并进行监听操作,可以使用$set:
// this.$set(object, key, value)
// 使用this.$set就可以监听到
this.$set(this.obj, 'a', Math.random())
复制代码
watch的handler方法的两个参数值相同
一个数据,如果值发生了变化,如果想要记录变化前和变化后的两个值,可以使用handler方法,第一个参数为变化后的新值,第二个为变化前的旧值。
但是如果这个值是复杂对象,如果想记录里面的属性的变化,使用handler,两个参数均为变化后的新值。
解决方法:
结合计算属性、序列化、反序列化生成新的对象,来避免此问题
data () {
return {
obj: {}
}
},
computed: {
// 如果想要得到差异内容,可以结合计算属性、序列化、反序列化生成新的对象,来避免此问题 。
obj2 () {
return JSON.parse(JSON.stringify(this.obj))
}
},
watch: {
obj2: {
handler (newVal, oldVal) {
console.log('data变化了')
console.log(newVal, oldVal)
},
deep: true
}
},
复制代码
全部代码
<template>
<div>
<button @click="clickFn">++++</button>
</div>
</template>
<script>
export default {
name: 'Mall',
data () {
return {
// !监听时给每一个属性都添加getter和setter,变化了,就触发handler函数,如果后期添加属性,这个属性不可以被监听到
// obj: {
// a: 10
// }
// !这种是不可以被监听到的
// 因为watch是通过Object.defineProperty()给对象的每一个现有属性增加监听器
// 在后面直接添加a属性,身上没有监听器,所以不会被监听到
obj: {}
}
},
computed: {
// 如果想要得到差异内容,可以结合计算属性、序列化、反序列化生成新的对象,来避免此问题 。
obj2 () {
return JSON.parse(JSON.stringify(this.obj))
}
},
watch: {
obj2: {
handler (newVal, oldVal) {
console.log('data变化了')
console.log(newVal, oldVal)
},
deep: true
}
},
methods: {
clickFn () {
// this.obj.a = Math.random()
// this.$set(object, key, value)
// 使用this.$set就可以监听到
this.$set(this.obj, 'a', Math.random())
}
}
}
</script>