计算属性概念
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如:
<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方法就可以了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。