computed和watch的区别

194 阅读4分钟

computed

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

computed的实现

微信图片_20221130185130.png

代码举例:普通写法

const vm = new Vue({
  data:{
    	  a:1
   },
    computed:{
    	b:function(){
        	return this.a+1
        },
        c(){            // es6写法,省略了:function
        return this.a+2
        }
    }
})
vm.b //2
vm.c //3

上面的属性只有getter效果,我们只能够读取计算属性的值

存取器写法

const vm=new Vue({
	data:{
          a: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

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

watch的实现

微信图片_20221130190234.png ### 代码
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变了,因为改变了b的地址
vm.b={c:2,x:3} //b变了,因为改变了b的地址
vm.b={c:3} //b 变了,因为改变了b的地址  b.cye变了
vm.b.c=100 //b.c变了,因为只是指定改变了b里面c的值
vm.d.e.f=4 // f变了,d变了,因为d做了deep: true,里面的任何一个发生变化则d都会变化。

如何区分别watch监听的数据是否发生了变化

  • 当监听属性的属性值为简单数据类型,就互相比较值,值不一样就触发watch
  • 如果监听的属性的属性值是复杂数据类型,就比较地址。地址不一样就触发watc

watch中的deep和immediate

  1. deep表示深侦听,也就是我设置的属性对应的属性值即使是复杂数据类型,加上deep:true,就全方位侦听,包括地址、内层属性的地址、内层属性的属性值。默认值为false
  2. immediate是表示当侦听开始时就先触发callback函数,默认为false一开始不会触发watch效果,而仅仅是侦听。

总结

  • 功能上:computed是计算属性,watch是监听一个值的变化,然后执行对应的回调。

  • 是否调用缓存:computed支持缓存,相依赖的数据发生改变才会重新计算;watch不支持缓存,只要监听的数据变化就会触发相应操作

  • 是否调用return:computed中的函数必须要用return返回,watch中的函数不是必须要用return。

  • computed默认第一次加载的时候就开始监听;watch默认第一次加载不做监听,如果需要第一次加载做监听,添加immediate属性,设置为true(immediate:true)

  • 使用场景:当一个属性受多个属性影响的时候,使用computed;当一条数据影响多条数据的时候,使用watch。

  • computed不支持异步,当computed内有异步操作时是无法监听数据变化的;watch支持异步操作

  • computed属性的属性值是函数,函数返回值为属性的属性值,computed中每个属性都可以设置setget方法。watch监听的数据必须是data中声明过或父组件传递过来的props中的数据,当数据变化时,触发监听器。