在 Vue 中通常我们会在模板绑定表达式,模板是用来描述视图结构的。如果模板中的表达式存在过多的逻辑性语句,那么整个模板就会变得特别的臃肿,可读性和维护性将会降低,因此为了简化逻辑,我们可以使用计算属性和侦听器来优化代码逻辑。
计算属性
计算属性是自动监听依赖值的变化,从而动态返回内容,监听是一个过程,在监听的值变化时,可以触发一个回调,并做一些事情。
1、基本用法
- <div id="app">
- <p>Original message: "{{ message }}"</p>
- <p>Computed reversed message: "{{ reversedMessage }}"</p>
- </div>
- var vm = new Vue({
- el: '#app',
- data: {
- message: 'Hello'
- },
- computed: {
- // 计算属性的 getter
- reversedMessage: function () {
- // `this` 指向 vm 实例
- return this.message.split('').reverse().join('')
- }
- }
- })
计算属性会基于响应式依赖进行缓存,只有原值 message 发生变化时,才会重新进行计算,否则会立即返回之前的计算结果。
2、计算属性缓存 vs 方法
我们可以使用 methods 来替代 computed,效果上两个都是一样的,但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。而使用 methods,在重新渲染的时候,函数总会重新调用执行。
- // 在组件中
- methods: {
- reversedMessage: function () {
- return this.message.split('').reverse().join('')
- }
- }
3、计算属性的 setter
计算属性默认只有 getter,当 fullName 为一个对象时,可为其设置 setter。
- var vm = new Vue({
- el: '#app',
- data: {
- firstName: 'Foo',
- lastName: 'Bar'
- },
- 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]
- }
- }
- }
- })
运行 vm.fullName = 'John Doe' 时,setter 会被调用,vm.firstName 和 vm.lastName 也会相应地被更新。
侦听属性
侦听属性 watch 中可以执行代码逻辑,如函数节流,Ajax 异步获取数据,甚至操作 DOM。
1、基本用法
- var vm = new Vue({
- el: "#app",
- data: {
- firstName: "Jack",
- lastName: "Ma",
- fullName: "Jack Ma",
- age: "18"
- }
- watch: {
- firstName: function(val) {
- console.log("触发一次,来自侦探器")
- this.fullName = val + " " + this.lastName;
- },
- lastName: function(val) {
- console.log("触发一次,来自侦探器")
- this.fullName = this.firstName + " " + val;
- }
- }
- })
2、watch 属性的深度监听和立即调用
使用 watch 来监听数据变化的时候除了常用到 handler 回调,其实其还有两个参数。
deep 为了发现对象内部值的变化,可以在选项参数中指定 deep: true。注意监听数组的变更不需要这么做。
- vm.$watch('someObject', callback, {
- deep: true
- })
- vm.someObject.nestedValue = 123
- // callback is fired
immediate 在选项参数中指定 immediate: true 将立即以表达式的当前值触发回调。
- vm.$watch('a', callback, {
- immediate: true
- })
- // 立即以 `a` 的当前值触发回调
总结
computed 属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算,主要当作属性来使用;watch 一个对象,键是需要观察的表达式,值是对应回调函数,主要用来监听某些特定数据的变化。
除此之外,有点很重要的区别是:计算属性不能执行异步任务,计算属性必须同步执行。也就是说计算属性不能向服务器请求或者执行异步任务。如果遇到异步任务,就交给侦听属性,watch 也可以检测 computed 属性。
最后 computed 能做的 watch 都能做,反之则不行,能用 computed 的尽量用 computed。
时间是一个好东西,记录的是学习的证据
评论