官网文档中的解释:
Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch——特别是如果你之前使用过 AngularJS。然而,通常更好的做法是使用计算属性而不是命令式的 watch 回调。
看以下例子:
<div id="demo">{{ fullName }}</div>
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
当姓或名改变时,调用firstName或lastName方法,最终目的都是改变fullName中的值,而且fullName中的值是依赖于firstName和lastName这两个变量的,如果我们使用computed方法那就不需要写两个方法来对数据进行监听,如下:
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
这样子的效果是一样的,并且减少了代码量。
那么这两者的区别在哪里呢?
比如现在有这么一个需求,当姓名更新时,延迟一秒再更新全名fullName中的数据,当我们使用computed的时候:
<!DOCTYPE html>
<html lang="en">
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<head>
</head>
<body>
<div id="demo">
姓:<input type="text" v-model="firstName" />
名:<input type="text" v-model="lastName" />
<div>全名:{{ fullName }}</div>
</div>
<script>
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
setTimeout(() => {
return this.firstName + ' ' + this.lastName
}, 1000)
}
}
})
</script>
</body>
显然我们是无法在computed中做一些异步操作的。
我们可以使用watch方法实现:
<div id="demo">
姓:<input type="text" v-model="firstName" />
名:<input type="text" v-model="lastName" />
<div>全名:{{ fullName }}</div>
</div>
<script>
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName:'Foo Bar'
},
watch:{
firstName(val){
setTimeout(()=>{
this.fullName = val + this.lastName
},1000)
},
lastName(val){
setTimeout(()=>{
this.fullName = this.firstName + val
},1000)
}
}
})
</script>
总结
共同点:
- 都可以用来对数据进行监听
不同点:
computed能做到的,watch都能做到,但是watch能做到的computed不一定都能做到- 当我们需要在数据变化时执行异步或开销较大的操作时,应该使用
watch,使用watch选项允许我们执行异步操作 (访问一个 API,防抖节流),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。 - 当我们的数据依赖于现有数据的时候应该使用
computed,因为computed的特性可以缓存数据,避免每次都需要重新计算.