watch的基本使用方法
watch:{
  watchData: function (value, oldValue) {
      console.log(value, oldValue)
  }
},

以上情况针对的是简单数据类型,比如数字,字符串,布尔类型等。若遇到复杂类型,如对象、数组,就需要使用深度监听

watch的深度监听

背景:普通的监听只能监听简单类型,如果需要监听某个对象的某个或者某几个属性,亦或者是监听数组中的某个元素变化,就需要使用深度监听

watch:{
  newTableData: {
    handler: function (value, oldValue) {
      console.log(value, oldValue)
    },
    deep: true
  }
},

使用上面的语法,会造成oldValue的值在每次newTableData变化时,都和value保持一致,变成当前最新的值,失去了oldValue的作用

原因:

vue官方解释是:变异 (不是替换) 对象或数组时,旧值将与新值相同,因为它们的引用指向同一个对象/数组。Vue 不会保留变异之前值的副本。

Tips:变异替换

变异

push() 往数组最后面添加一个元素,成功返回当前数组的长度
pop() 删除数组的最后一个元素,成功返回删除元素的值
shift() 删除数组的第一个元素,成功返回删除元素的值
unshift() 往数组最前面添加一个元素,成功返回当前数组的长度
splice() 有三个参数,第一个是想要删除的元素的下标(必选),第二个是想要删除的个数(必选),第三个是删除 后想要在原位置替换的值
sort() sort() 使数组按照字符编码默认从小到大排序,成功返回排序后的数组
reverse() reverse() 将数组倒序,成功返回倒序后的数组

替换

不会改变原数组,但总是返回一个新数组

filter filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
concat concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组
slice slice() 方法可从已有的数组中返回选定的元素。该方法并不会修改数组,而是返回一个子数组

解决方法

使用序列化和反序列化

  将计算属性和侦听器搭配使用,

    1.首先将需要侦听的属性通过JSON.parse和stringfy进行深拷贝,

    2.然后用侦听器去侦听计算属性,这样就可以得到原来的旧值了

data: () {
    return{
    // 数据为复杂类型
        tableAll:{
           tableData:[]
        }
    }
},

computed:{
// 使用计算属性进行深拷贝
  newTableData(){
    return JSON.stringify(this.tableAll.tableData)
  }
},
watch:{
// 监听拷贝后的数据
  newTableData: {
    handler: function (value, oldValue) {
        let obj = JSON.parse(value);
            let obj2 = JSON.parse(oldValue);
        console.log(obj, obj2)
    },
    deep: true
  }
}