watch和computed详解

229 阅读3分钟

computed :一个数据受多个数据影响

计算属性,它会根据data数据的数据对象做计算处理,就类似于getter跟setter一样创造一个存取器属性。它有个特点,就是Vue内部做了缓存处理,只有它的依赖属性发生了变化,它才会重新计算并且触发渲染。否则不会再次触发计算。

const vm=new Vue({
    data:{n:1},
    computed:{
        a:{
            get(){return this.n+1},
            set(value){this.n=value-1}
        }   
    
    }
})
vm.n // 1
vm.a =3
vm.n //2

上面的写法会影响到响应式属性n,当设置vm.a时,vm.n也会发生变化。

computed默认有缓存效果,当计算属性没有发生变化时,不会重新计算更不会重新渲染。

watch:一个数据影响多个数据

在vue中它是一个侦听器,会对依赖属性进行侦听(观察)。当侦听的属性发生变化时,就会执行一个函数。值得注意的是,watch是异步函数,如果我们的属性需要在侦听后再执行某个变化,可以使用**$nextTick**这个API

let vm = new Vue({
    data: {
        a: 1,
        b: {
            c: 2
        },
        d: {
            e: {
                f: 3
            }
        },
    },
    watch: {
        a(newvalue, oldValue) {
            console.log( 'a变了')
        },
        b: {
            handler: function (v, oldv) {
                console.log("b变了")
            },
            immediate: true //在侦听开始时就调用回调函数
        },
        'b.c': function (v, oldv) {
            console.log("b.c变了")
        },
        d: {
            handler: function (v, oldv) {
                console.log("d变了")
            },
            deep: true // 深侦听,只要d、d.e包括d.e.f发生变化都会侦听到
        }
    }
})
// vm.b 变了
vm.a=2 //a变了
vm.b={c:2} // b变了
vm.b={c:2,x:3} //b变了
vm.b={c:3} //b 变了  b.c变了
vm.b.c=100 //b.c变了
vm.d.e.f=4 //d变了

当属性值为简单数据类型时,以vm.a为例,由于此时属性值是简单数据类型,所以很容易监听到其发生变化。此时属性值!==改变后的属性值,就会触发watch

当属性值为复杂数据类型时,以vm.b为例子,它保存了{c:2}这个值。 如果它的内存地址发生变化,也就是说原先的{c:2}和我后来设置的{c:2}的内存地址不一致,所以就会触发b变了,

结论

当监听属性的属性值为简单数据类型,就互相比较值,值不一样就触发watch

如果监听的属性的属性值是复杂数据类型,就比较地址。地址不一样就触发watch

deep 和 immediate

deep表示深侦听,也就是我设置的属性对应的属性值即使是复杂数据类型,加上deep,就全方位侦听,包括地址、内层属性的地址、内层属性的属性值。

immediate是表示当侦听开始时就先触发callback函数,默认为一开始不会触发watch效果,而仅仅是侦听。

使用场景

当我们试图通过数据对象来创造另一个属性时,推荐使用computed,比如判断数据是否展示

当我们试图通过侦听数据对象的改变来做点什么(比如执行一个函数),我们就可以使用watch,在使用watch时尤其要注意其为异步执行的特点。