vue用watch监听对象,打印oldValue和newValue相同的问题

vue用watch监听对象,打印oldValue和newValue相同的问题

背景

做节目设计器时候,当组件超出限制大小时,需要回滚此次操作,但是数据没有备份,拿不到旧数据。因此在watch中监听变化对象,达到旧数据缓存的能力。

data(){
	return {
		obj:{a:1,b:2,c:{d:3,e:4}},
		oldObj:null
	}
},
watch: {
    obj: {
      handler: function (newVal, oldVal) {
        console.log('newVal', newVal, 'oldVal', oldVal)
        this.oldObj = this.obj
      },
      deep: true
    }
}

设想是这样,可是当我们实践发现,newVal,和oldVal打印值相同,这是为什么呢?

原理

其实很简单,因为对象指向的是一个对象,对象是引用类型。所以在改了数据之后,oldVal也会随之变化。

Vue官方的解释是:在变更(不是替换)对象或数组时,新值与旧值相同,因为他们指向同一数组或对象,Vue不会保留变更前值的副本。

解决方法

我们可以用计算属性并配合JSON.stringify()来进行保存。
修改后代码:

computed: {
  computedObj () {
    return JSON.parse(JSON.stringify(this.obj))
  }
}
watch: {
   computedObj: {
     handler: function (newVal, oldVal) {
       console.log('newVal', newVal)
       console.log('oldVal', oldVal)
       this.oldObj = oldVal
     },
     deep: true
   }
 }

这样就实现了我们想要的效果。缓存了旧数据。如果需要回滚操作,只需要赋值缓存数据即可。

同样使用场景还可以是:我们需要监听多个字段时,就可以把它们放到一个对象中。然后去监听这个对象。

附加

如果是第二种场景想节省性能的话,可以加一个防抖函数进去,防止页面初始化被调用多次。watch监听虽好,但还是少用、小心用为妙啊!

搞定,下班!

你可能感兴趣的:(前端知识,vue.js,javascript,前端)