林秀栋的技术博客

watch监听数组变化无法执行问题

当数组a的某一项变化时(比如a.splice(0,1,’newVal’)),想获取变化前后的值,直接watch该数组无法获得;而如果直接改变整个数组(比如a=[‘newVal’])没问题

new Vue({
    //...
	data: {
		a: [1,2]
	},
	methods: {
	    //点击某按钮后运行
		aa: function(){
			if(this.a[0] == 1){
				this.a.splice(0,1,2)
				//this.a = [2,2]
			}else{
				this.a.splice(0,1,1)
				//this.a = [1,2]
			}
		}
	},
	watch: {
		a: function(newVal, oldVal){
		    //newVal和oldVal都是改变后的值,即都为newVal
		    //如果上文aa()中赋值改为this.a=[2,2],可以正常获取这两个参数
			console.log(newVal);
			console.log(oldVal);
		}
	}
})

解决方法:设置一个缓冲值

new Vue({
    //...
    computed: {
        //如果直接在下面watch写a时返回的newValue和oldValue会是相同的值
        //需要在computed中设置a2进行缓冲
        //相当于每次a中内容改变就对a2进行重新赋值,以a2来展示
        a2: function() {
            return deepClone(this.a);   //对a进行深拷贝
        }
    },
    watch: {
        a2: function(newValue, oldValue){
            //新旧值不同
		    //alert(JSON.stringify(oldValue))
            //alert(JSON.stringify(newValue))
            //循环判断不同的值
            for (var i = 0; i < newValue.length; i++) {
                for (var j = 0; j < newValue[i].length; j++) {
                    if (oldValue[i][j] != newValue[i][j]) {
                        //do something
                    }
                }
            }
		}
    }
})

对象也有同样问题,改变其中某个值(比如a.b=1)时获取到的newVal和oldVal相同,也可以使用上面思路解决。

注意对象watch时一般要用深度监听,但这里其实直接改变了整个对象(a={b:111}),而非改变其中某一项,所以普通监听也可以执行。

而数组好像也应该用深度监听的,但用splice后不需要深度监听也可以触发。即使是深度监听a[0]=1这样的赋值也无法触发,因此并没有找到使用深度监听的理由