Vue学习笔记 - 构造选项之computed和watch

190 阅读2分钟

问题引入:data 变化时除了更新视图,还能做什么?

1、computed - 计算属性

即被计算出来的属性,它是一个函数,直接引用该属性即显示函数的返回值。

两种写法:

  1. 函数
computed:{
    xxx(){...}
}
  1. getter/setter
computed:{
    xxx:{
        get(){...}
        set(value){...}
    }
}

用途:展示对 data 中的数据进行处理后的结果

{
    data:{
        a: 0
    },
    
    computed:{
        processA(){
            return ... //a处理后的值
        }
    },
    
    template:`
        <div>{{processN}}</div>
    `
}

当 data 中的数据变化时,触发视图更新,其中依赖于 data 的计算属性会重新计算(即执行了相应的函数)

计算属性有缓存处理,如果其依赖的 data 没有变化,则不会重新计算

2、watch - 侦听

用途:当 data 变化时,执行一个函数

{
    data:{
        n:0,
        obj:{
            a: 0
        }
    },
    watch:{
        n(newValue, oldValue){...}, //侦听n
        'obj.a'(){...} //侦听obj.a
    }
}

执行时会传入新值(newValue)、旧值(oldValue

【注】

watch 是异步的,它不会在n变化后立即执行,而是在当前同步任务结束后才会执行 watch

Vue 提供了 this.$nextTick 方法来创建新异步任务:

this.$nextTick(fn, 0)

上述 watch 的写法在第一此渲染时并不会执行,写为如下的对象形式,则第一次渲染也会执行:

{
    watch:{
        'obj.a': {
            handler(){...}, //待执行的函数
            immediate: true
        }
    }
}

何为 data 变化?

考虑如下 data:

data:{
    n:0,
    obj:{
        a: 0
    }
}

侦听其中的n obj obj.a

  • 改变 n = 1 ---> 执行n的侦听
  • 改变 obj.a = 1 ---> 仅执行obj.a的侦听
  • 改变 obj = {a: 0} ---> 仅执行obj的侦听,obj.a的侦听不执行

【结论】:简单类型看值的变化,复杂类型看地址的变化

如何实现改变 obj.a,obj 的侦听亦执行?---------> deep: true

watch:{
    obj:{
        handler(){...},
        deep:true
    }
}

watch 完整用法

watch:{
    a: function(){},
    b: 'methodName', //methods 中的方法
    c: {
        handler(){},
        deep: true, 
        immediate: true
    },
    d: [f1,f2,f3], //依次执行f1 f2 f3 ...
    'obj.e': function(){}
}

此外,还可以用 Vue 实例的 '$watch' 方法:

vm.$watch('f', fn, {deep:true, immediate:true})

3、总结:computed 和 watch 区别

两者均会在 data 变化时执行某个函数,但也有区别

  1. computed

目的是得到一个依赖于 data 的值,虽然写为方法的形式,但可以当作 Vue 实例的属性一样,不用加括号直接获取其返回值。

并且,computed 还做了缓存处理,即 data 变化时,若被 computed 依赖的部分没有变,则不会再次进行计算。

  1. watch

watch 则是用来监听 data 中的属性,当其变化时,执行回调。其目的并非一定要得到某个依赖于 data 的值,因此它的使用情景可以比 computed 更广泛。