模板内的表达式很是便利,可是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板太重且难以维护。例如:html
<div id="example"> {{ message.split('').reverse().join('') }} </div>
在这个地方,模板再也不是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量 message 的翻转字符串。当你想要在模板中屡次引用此处的翻转字符串时,就会更加难以处理。vue
因此,对于任何复杂逻辑,你都应当使用计算属性
简单的理解为:数组
1.计算属性其实就是 Vue 实例的一个属性
2.计算属性通常依赖传统的 Vue 实例属性
3.计算属性通常是经过运算获得的属性
缓存
简单的写法app
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('') } } }
HTMLide
<p>Reversed message: "{{ reversedMessage() }}"</p>
JS函数
// 在组件中 methods: { reversedMessage: function () { return this.message.split('').reverse().join('') } }
计算属性是基于它们的依赖进行缓存的,只有在它相关的依赖发生改变时才会从新求值,即计算属性会对计算出来的结果进行缓存,
这就意味着只要 message
尚未发生改变,屡次访问 reversedMessage
计算属性会当即返回以前的计算结果,而没必要再次执行函数
性能
方法是每次从新渲染时,调用方法将总会再次执行函数,开销比较大ui
咱们为何须要缓存?
假设咱们有一个性能开销比较大的计算属性 A,它须要遍历一个巨大的数组并作大量的计算。而后咱们可能有其余的计算属性依赖于 A 。若是没有缓存,咱们将不可避免的屡次执行 A 的 getter!若是你不但愿有缓存,请用方法来替代
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
一开始被渲染出来的时候是空值,以下所示:
如上所述,一开始被渲染出来的时候,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,默认值为false,表明是否深度监听,
总的来讲,计算属性倾向于格式化/处理当前的数据,而 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方法就能够了。