Vue-computed 和 watch 的区别

462 阅读3分钟

1.computed:计算属性

  1. Vue的进阶属性
  2. 计算属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。
  3. 也就是说某个依赖 (比如非响应式属性) 在该vm实例范畴之外,则计算属性是不会被更新的。
  4. 所以我们不希望使用依赖缓存的时候可以使用基本属性methods代替之。
  5. 注意如果你为一个计算属性使用了箭头函数,则 this 不会指向这个vm组件的实例,不过你仍然可以将其实例作为函数的第一个参数来访问。
用法

官方

{ [key: string]: Function | { get: Function, set: Function } }

var vm = new Vue({
  data: { a: 1 },
  computed: {
    // 仅读取
    aDouble: function () {
      return this.a * 2
    },
    // 读取和设置
    aPlus: {
      get: function () {
        return this.a + 1
      },
      set: function (v) {
        this.a = v - 1
      }
    }
  }
})
vm.aPlus   // => 2
vm.aPlus = 3
vm.a       // => 2
vm.aDouble // => 4
  1. aDouble 值是个函数,可以直接通过key值调用函数
  2. aPlus 值是个对象且有get和set属性

2.watch:监听属性

  1. Vue的进阶属性
  2. Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动。
  3. 数据变化,执行一个异步的函数(且非箭头函数)。
  4. 有immediate和deep属性。
  5. 而且不应该使用箭头函数来定义watch函数,因为箭头函数绑定了父级作用域的上下文,所以this不会按照期望指向vue实例,此时的this将会是undefined。
用法

{ [key: string]: string | Function | Object | Array }

官方实列

var vm = new Vue({
  data: {
    a: 1,
    b: 2,
    c: 3,
    d: 4,
    e: {
      f: {
        g: 5
      }
    }
  },
  watch: {
    a: function (val, oldVal) {
      console.log('new: %s, old: %s', val, oldVal)
    },
    // 等价写法
     b(val, oldVal) {
      console.log('new: %s, old: %s', val, oldVal)
    },
    // 方法名
    b: 'someMethod',
    // 该回调会在任何被侦听的对象的 property 改变时被调用,不论其被嵌套多深
    c: {
      handler: function (val, oldVal) { /* ... */ },
      deep: true
    },
    // 该回调将会在侦听开始之后被立即调用
    d: {
      handler: 'someMethod',
      immediate: true
    },
    e: [
      'handle1',
      function handle2 (val, oldVal) { /* ... */ },
      {
        handler: function handle3 (val, oldVal) { /* ... */ },
        /* ... */
      }
    ],
    // watch vm.e.f's value: {g: 5}
    'e.f': function (val, oldVal) { /* ... */ }
  }
})
vm.a = 2 // => new: 2, old: 
import Vue from "vue";

new Vue({
  data: {n: 0,},
  watch: {
    n() {console.log(`n发生变化时会执行我`);}
  },
  methods: {
    add() {this.n += 1;}
  },
  template: `
    <div>
      {{n}}
      <button @click=add>点我+1</button>
    </div>
    `
}).$mount("#app");

每次n发生变化时,就会出发watch的n方法

3.computed vs watch

Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。当你有一些数据需要随着其它数据变动而变动时,你很容易滥用watch。然而,通常更好的做法是使用计算属性而不是命令式的 watch 回调。细想一下这个例子:

<div id="demo">{{ fullName }}</div>
var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar',
    fullName: 'Foo Bar'
  },
  watch: {
    'data.firstName': function (val) {
      this.fullName = val + ' ' + this.lastName
    },
    'data.lastName'() {
      this.fullName = this.firstName + ' ' + val
    }
  },
computed: {
    fullName: function () {
    return this.firstName + ' ' + this.lastName
    }
  }
  }
})

computed是不是比watch简洁!!!! watch

  1. 第一次刷新的时候的时候页面显示为空,因为firstName和lastName只是从无到有,称不上为变化。
  2. 怎么样使第一次也运行结果呢
 watch:{
    'data.firstName':{
      handler(){
        this.fullName = val + ' ' + this.lastName
      },
     immediate:true  //第一次也运行一下结果
    },
    'data.lastName'() {
        handler(){
        this.fullName = this.firstName + ' ' + val
      },
      immediate:true  //第一次也运行一下结果
    }
  1. 什么又是watch的deep属性呢
  • 此处的意思是比如我监听data的时候,是否忘深了看, 比如data.fullName变化的时候,data是否也变了呢
  • 这根据你的需求来,认为data也变了那么,deep:ture
  • 反之认为data没变那么,deep:false 就是不往内部看

总结

  1. 如果一个数据依赖于其他数据,那么把这个数据设计为computed的
  2. 如果你需要在某个数据变化的时候做一些事情,使用watch来观察这个数据变化
  3. 当你有一些数据需要随着其它数据变动而变动时,通常更好的做法是使用计算属性而不是命令式的 watch回调。