一、从demo出发
先看一个简单场景
<template>
<section>
<input v-model="obj.a">
</section>
</template>
<script>
export default {
data () {
return {
obj: {
a: 1
}
}
},
watch: {
obj: {
handler (newVal, oldVal) {
console.log('newVal', newVal)
console.log('oldVal', oldVal)
},
deep: true
}
}
}
</script>
此时,我们已经设置deep: true
才能监听到obj.a
的变化
而在打印的结果发现新值和旧值却是一样的
二、窥探源码
其实看一眼源码就明白了
我们在 handler函数中增加debugger
调试程序
原来, 其实就是赋值
对于引用类型,
赋值存的是地址,地址指向堆内存存储的值
相信大家都懂
而其实,官方也说明了
三、解决办法
那如何解决呢?
1.用watch指向监听的基本类型
<template>
<section>
<input v-model="obj.a">
</section>
</template>
<script>
export default {
data () {
return {
obj: {
a: 1
}
}
},
watch: {
'obj.a': { // watch指向监听的基本类型
handler (newVal, oldVal) {
console.log('newVal', newVal)
console.log('oldVal', oldVal)
},
deep: true
}
}
}
</script>
这种方法,简单明了
就是把对象属性(基本类型)的作为监听对象
2.使用computed
<template>
<section>
<input v-model="obj.a">
</section>
</template>
<script>
export default {
data () {
return {
obj: {
a: 1
}
}
},
computed: {
newObj () {
// 对 obj 进行深拷贝
return JSON.parse(JSON.stringify(this.obj))
}
},
watch: {
newObj: { // 监听新值
handler (newVal, oldVal) {
console.log('newVal', newVal)
console.log('oldVal', oldVal)
},
deep: true
}
}
}
</script>
这种方法利用computed缓存依赖需要监听的对象
然后又对存在对象进行一个监听,从而获取前后值的变化
总结一下:
对于以上两种方法,
方法一会比方法二更‘轻’一点,性能更加,也比较推荐
感谢阅读