聊聊vue的计算属性computed与侦听器watch

2019-10-01  本文已影响0人  CalvinXie

聊聊vue的计算属性和帧听器

th (1).jpg

vue的计算属性computed和侦听器watch都是监听数据变化。

computed

顾名思义,computed 中文为计算;所以其在vue单文件组件中做的就是对数据进行简单的一些逻辑计算,这在项目开发中很方便我们队原始数据处理。** 重要的是计算属性基于它们的响应式依赖进行缓存的。**只有当响应依赖关系变了即值发生变化了才会重新计算。否则,直接利用缓存,这样既避免多次调用函数又提升性能。

const vm = new Vue({
  el: '#demo',
  data: {
   firstName: 'kevin',
   lastName: 'Xie'
  },
  computed: {
   fullName () {
     return this.firstName + ' ' + this.lastName
   }
  }   
})

computed 有两个属性getter 和 setter,上面我们只用到了getter属性,默认是getter属性,如果需要主动去改变getter的值,可以通过setter来实现。

// ...
computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}
// ...

watch

watch 则多数监听数据改变去执行异步操作和逻辑复杂的操作。同样watch也是在当值发生改变才会触发,不过没有缓存机制。

const vm = new Vue({
  el: '#demo2',
  data: {
    visible: false
  },
  watch: {
    visible (newVal, oldVal) {
        // ...some code
    }
  }
})

watch的类型可以是{ [key: string]: string | Function | Object | Array }
一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性。

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: '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: 1

Vue.js-cover.png

** 注意,不应该使用箭头函数来定义 watcher 函数 (例如 searchQuery: newValue => this.updateAutocomplete(newValue))。理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.updateAutocomplete 将是 undefined**
有时候computed可以和watch配合使用,比如你要同时监听两个值得变化。可以这样写:

const vm = new Vue({
  el: '#demo3',
  data: {
    value1: '',
    value2: ''
  },
  computed: {
    doubleVal () {
      return {
        val1: this.value1,
        val2: this.value2
      }
    }    
  },
  watch: {
    doubleVal(v) {
     console.log(v) // 这里的v就包括两个值
    }
  }
})

还有一点在开发可能会遇到,就是watch一个对象时,只有当给对象赋值了才触发watch,但我们需求是要在初始化对象时就触发,这个时候deep属性就派上用场了。

const vm = new Vue({
  el: '#demo4',
  data: {
    obj: {
      a: 1,
      b: 'test'
    }
  },
  watch: {
    obj: {
      handler(v) {
       console.log(v) // 不会执行
      }
    }
  }
})
const vm = new Vue({
  el: '#demo5',
  data: {
    obj: {
      a: 1,
      b: 'test'
    }
  },
  watch: {
    obj: {
      handler(v) {
       console.log(v) // {a: 1, b: 'test'}
      },
      deep: true
    }
  }
})

但是这样会影响性能,使得对象某一个属性发生改变时vue就啊哟深度遍历整个对象,对每个属性都会触发handler函数,建议采用字符串形式监听

const vm = new Vue({
  el: '#demo6',
  data: {
    obj: {
      a: 1,
      b: ''
    }
  },
  watch: {
    'obj.a': {
      handler(v) {
       console.log(v) // 1
      }
    }
  }
})

还有一个场景是当某个值初始化但watch没有监听到,然而我们同样需要立即监听,则immediate属性派上用场了。

const vm = new Vue({
  el: '#demo7',
  data: {
    say: 'hello world'
  },
  watch: {
    say: {
      handler(v) {
       console.log(v) // 不会执行
      }
    }
  }
})
const vm = new Vue({
  el: '#demo8',
  data: {
    say: 'hello world'
  },
  watch: {
    say: {
      handler(v) {
       console.log(v) // hello world
      },
      immediate: true
    }
  }
})

watch在不用的时候需要注销它,在单文件组件销毁时vue会帮我们自动注销,但如果我们没在单文件组件使用,app.$watch调用后会返回一个值,就是unWatch方法,你要注销 watch 只要调用unWatch方法就可以了。

const unWatch = app.$watch('text', (newVal, oldVal) => {
  console.log(`${newVal} : ${oldVal}`)
})

unWatch() // 手动注销watch

好了,今天vue的计算属性和帧听器就聊到这了, 欢迎大家批评指正。


7c9f3d7e721357d22c3d0b1489ef25aa7d5f08b28aa4-aZGibK_fw658.jpg
上一篇下一篇

猜你喜欢

热点阅读