1
计算属性概念

模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如:

<div id="example">
  {{ message.split('').reverse().join('') }}
</div>

在这个地方,模板不再是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量 message 的翻转字符串。当你想要在模板中多次引用此处的翻转字符串时,就会更加难以处理。

所以,对于任何复杂逻辑,你都应当使用计算属性

简单的理解为:

1.计算属性其实就是 Vue 实例的一个属性

2.计算属性一般依赖传统的 Vue 实例属性

3.计算属性一般是通过运算得到的属性

计算属性的get和set

简单的写法

computed: {
  reversedMessage() {
    return this.message.split('').reverse().join('')
  }
}

完整版写法

computed: {
    reversedMessage: {
        get() { //获取值
           return this.message.split('').reverse().join('')
        },
        set(val) { // set方法:设置值
         this.message = val.split('').reverse().join('')
        }
    }
}
计算属性VS方法

HTML

<p>Reversed message: "{{ reversedMessage() }}"</p>

JS

// 在组件中
methods: {
  reversedMessage: function () {
    return this.message.split('').reverse().join('')
  }
}

计算属性是基于它们的依赖进行缓存的,只有在它相关的依赖发生改变时才会重新求值,即计算属性会对计算出来的结果进行缓存,这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数

方法是每次重新渲染时,调用方法将总会再次执行函数,开销比较大

我们为什么需要缓存?

假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A 。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代
计算属性 vs 侦听属性

watch
放在 data 中的对象,一旦发生改变就会执行相应的操作,当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的

<div>
  <p>FullName: {{fullName}}</p>
  <p>FirstName: <input type="text" v-model="firstName"></p>
</div>
new Vue({
  el: '#root',
  data: {
    firstName: 'Joy',
    lastName: 'lqy',
    fullName: ''
  },
  watch: {
    firstName(newName, oldName) {
      this.fullName = newName + ' ' + this.lastName;
    }
  } 
})

watch 中的对象在 data 中已经定义了,当我们输入firstName后, watch监听每次修改变化的新值,然后计算输出fullName。也就是上面的代码中,fullName 一开始被渲染出来的时候是空值,如下所示:

watch的高级用法

handler方法和immediate属性

如上所述,一开始被渲染出来的时候,fullName是空值,如果想要一开始就让最初绑定的值执行该怎么办尼?别急,我们只需要给firstName绑定一个handler方法,之前我们写的watch方法其实默认写的就是这个handler,Vue.js会去处理这个逻辑,最终编译出来其实就只这个handler,设置immediate:true代表如果在 wacth 里声明了 firstName 之后,就会立即先去执行里面的handler方法,如果为 false就跟我们以前的效果一样,不会在绑定的时候就执行

修改后的代码如下:

 watch: {
    firstName: {
        handler(newName, oldName) {
            this.fullName = newName + ' ' + this.lastName;
        },
        // 代表在wacth里声明了firstName这个方法之后立即先去执行handler方法
        immediate: true
    }
}

结果如下:

deep属性

deep,默认值为false,代表是否深度监听,

总的来说,计算属性倾向于格式化/处理当前的数据,而 watch 倾向于执行数据变化需要进行的操作

注销watch

为什么要注销 watch?因为我们的组件是经常要被销毁的,比如我们跳一个路由,从一个页面跳到另外一个页面,那么原来的页面的 watch 其实就没用了,这时候我们应该注销掉原来页面的 watch 的,不然的话可能会导致内置溢出。好在我们平时 watch 都是写在组件的选项中的,他会随着组件的销毁而销毁。

const app = new Vue({
  template: '<div id="root">{{text}}</div>',
  data: {
    text: 0
  },
  watch: {
    text(newVal, oldVal){
      console.log(`${newVal} : ${oldVal}`);
    }
  }
});

但是,如果我们使用下面这样的方式写 watch,那么就要手动注销了,这种注销其实也很简单

const unWatch = app.$watch('text', (newVal, oldVal) => {
  console.log(`${newVal} : ${oldVal}`);
})
unWatch(); // 手动注销watch

app.$watch调用后会返回一个值,就是unWatch方法,你要注销 watch 只要调用unWatch方法就可以了。

参考

计算属性和侦听器
Vue.js中侦听器(watch)的高级用法


橙汁味的西瓜酱
27 声望5 粉丝

Amateur painter