computed 和 watch 的区别是什么?
computed
- 它是计算属性。主要用于值的计算并一般会返回一个值。所以它更多⽤于计算值的场景
- 它具有缓存性。当访问它来获取值时,它的 getter 函数所计算出来的值会进行缓存
- 只有当它依赖的属性值发生了改变,那下⼀次再访问时才会重新调⽤ getter 函数来计算
- 它适⽤于计算⽐较消耗性能的计算场景
- 必须要有一个返回值
watch
- 它更多的是起到 “观察” 的作⽤,类似于对数据进行变化的监听并执行回调。
- 主要⽤于观察
props或 本组件 data 的值,当这些值发生变化时,执⾏处理操作 - 可以监听数据发生变化,可以监听的数据有(props、data、computed、$route) watch 侦听器如果监听的是一个对象,需要开启深度监听
- 不一定要返回某个值、
watch:{
num:{
// 监听数据发生变化的处理函数
handler(newNum) {
console.log(newNum)
},
// 是否开启深度监听
deep: true
}
}
如果想实现首次监听配置 immediate 为 true
建议
- 当目的是进⾏数值计算,且依赖于其他数据,那么推荐使用
computed - 当需要在某个数据发生变化的, 同时做⼀些稍复杂的逻辑操作,那么推荐使⽤
watch
computed 和 watch哪个可以异步
计算属性能(computed)完成的功能监听属性都能完成
比如计算两个数的和
<body>
<div id="app">
<p>总和{{adden}}</p>
输入的值1<input type="text" v-model:value="a" >
输入的值2<input type="text" v-model:value="b">
</div>
<script src="../vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
a:"",
b:"",
adden:"",
},
//监听属性实现
watch:{
a(val){
this.adden=this.b*1+val*1
},
b(val){
this.adden=this.a*1+val*1
}
},
// 计算属性实现
// computed: {
// adden(){
// console.log(this);
// return this.a*1+this.b*1
// }
// },
})
</script>
</body>
计算属性(computed)不能进行异步操作
因为计算属性(computed)是通过return返回值传递参数 异步操作的时候return是没有意义的
以定时器(setTimeout)举例
很明显58行打印的并不是setTimeout中return的值,而是对应的setTimtout()的 ID
详情可以看
setTimeout() - 简书 (jianshu.com) www.jianshu.com/p/9b389c99d… 异步函数的返回值都不是用return返回的
所以vue中的计算属性(computed)不能使用异步函数
如果想让两个数的和隔一秒在出现 计算函数是不行的
<body>
<div id="app">
<p>总和{{adden}}</p>
输入的值1<input type="text" v-model:value="a" >
输入的值2<input type="text" v-model:value="b">
</div>
<script src="../vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
a:"",
b:"",
// adden:"",
},
//监听属性
// watch:{
// a(val){
// this.adden=this.b*1+val*1
// },
// b(val){
// this.adden=this.a*1+val*1
// }
// },
<** 这是错误的 **>
computed: {
adden(){
console.log(this);
return setTimeout(()=>{
console.log(this.a);
return this.a*1 + this.b*1
},1000)
}
},
})
</script>
</body>
此时adden返回的是setTimeout的Id
监听属性(watch)
当被监听的属性变化时会自动调用预定义函数
watch可以进行异步操作
<body>
<div id="app">
<p>总和{{adden}}</p>
输入的值1<input type="text" v-model:value="a" >
输入的值2<input type="text" v-model:value="b">
</div>
<script src="../vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
a:"",
b:"",
adden:0,
},
//监听属性
watch:{
a(val){
setTimeout(()=>{
this.adden=this.b*1+val*1
},1000)
},
b(val){
this.adden=this.a*1+val*1
}
},
// computed: {
// adden(){
// console.log(this);
// return setTimeout(()=>{
// console.log(this.a);
// return this.a*1 + this.b*1
// },1000)
// }
// },
})
</script>
</body>
以定时器为例
所有不被vue管理的函数(定时器的回调,ajax的回调函数等)最好写成箭头函数这样this的指向才是vm或者组件实例对象,被vue管理的函数最好不要使用箭头函数,this会指向为被定义(箭头函数绑定的是父级作用域的上下文)