浅聊一下
嗖的一下,这个年就差不多过去了,还在家里的学生党将要面临的是即将到来的金三银四,本篇文章要来讲的是面试时经常会被问到的一个知识点------computed和watch的区别
复习
既然都聊到这了,我们就先来复习一下 computed和watch
computed
computed是vue中的一个计算属性,我们通过一个例子来看什么是computed和为什么需要computed
首先请出坤坤当特约嘉宾,定义了一个person的响应式对象,名字叫坤坤,爱好唱、跳、rap、篮球,将坤坤展示在页面上,我们先看不使用computed的写法
html
<template>
<div>{{person.name}}</div>
<div>{{person.hobby.length > 0 ?'你干嘛':'哎哟!'}}</div>
</template>
<script setup>
import { computed, ref } from 'vue';
let person = ref({
name:'坤坤',
hobby:['唱','跳','rap','篮球']
});
</script>
如果坤坤有爱好,则通过计算 person.hobby.length > 0 ?'你干嘛':'哎哟!'
显示"你干嘛",反之则显示"哎哟!",来看效果
我们可以看到,通过这种在花括号中写表达式的方式确实是可以来计算属性的,但是在花括号中只能进行简单的一些计算,如果在模板中写太多的逻辑,会让你的代码看起来十分的臃肿,难以维护,于是computed应运而生...
html
<template>
<div>{{person.name}}</div>
<div>{{active}}</div>
</template>
<script setup>
import { computed, ref } from 'vue';
let person = ref({
name:'坤坤',
hobby:['唱','跳','rap','篮球']
});
let active = computed(()=>{
return person.value.hobby.length > 0 ?'你干嘛':'哎哟!'
})
</script>
来看,也是同样的效果
仔细想想,我们还有没有别的写法...
html
<template>
<div>{{person.name}}</div>
<div>{{method()}}</div>
</template>
<script setup>
import { computed, ref } from 'vue';
let person = ref({
name:'坤坤',
hobby:['唱','跳','rap','篮球']
});
const method = ()=>{
return person.value.hobby.length > 0 ?'你干嘛':'哎哟!'
}
</script>
费那么大功夫,我直接用method不香吗?为什么还要用computed?这就不得不提到computed与method的区别了
computed与method的区别
来通过代码发现问题,来分别输出这么多次
我嘞个豆!computed只触发了一次,说明了什么?computed是有缓存的,而method没有...用谁香一点不用我多说
总结:
计算属性:计算属性值会基于其响应式依赖被缓存,一个计算属性仅会在其响应式依赖更新时才重新计算
方法:方法调用总是会在渲染发生时再次执行函数
computed计算
我们的computed主要是用来基于其他响应式数据计算出一个新的属性值,那么当我们依赖的响应式数据发生变更时,computed就会触发(开局触发一次)。来看例子
js
<template>
<div>{{person.name}}</div>
<div>{{active2}}</div>
<button @click="person.hobby.pop()">减爱好</button>
</template>
<script setup>
import { computed, ref } from 'vue';
let person = ref({
name:'坤坤',
hobby:['唱','跳','rap','篮球']
});
let active2 = computed(()=>{
console.log('computed触发');
return person.value.hobby.join(',');
})
</script>
点击"减爱好"给坤坤减去爱好,来看效果
点击一下
computed触发,坤坤最喜欢的篮球被减掉了...
watch
watch是一个侦听器,当侦听的响应式属性发生改变时,watch触发,同样的请上特约嘉宾
html
<template>
<div>{{person.name}}</div>
<div>{{person.age}}</div>
<div>{{active2}}</div>
<button @click="person.hobby.pop()">减爱好</button>
<button @click="person.age++">坤坤长大</button>
</template>
<script setup>
import { computed, ref, watch } from 'vue';
let person = ref({
name:'坤坤',
hobby:['唱','跳','rap','篮球'],
age:18
});
let active2 = computed(()=>{
console.log('computed触发');
return person.value.hobby.join(',');
})
watch(() => person.value.age, (newAge, oldAge) => {
console.log(`坤坤从${oldAge}长到${newAge}岁了`);
})
</script>
在 Vue 3 中,使用组合式 API 的 watch
函数来监视响应式数据的变化时,watch
函数接收两个参数:
- 第一个参数是一个函数或者一个 getter 函数,用于获取要监视的响应式数据。这个函数可以返回任何需要被监视的响应式数据,例如
person.value.age
,或者其他计算属性、ref 等。 - 第二个参数是一个回调函数,用于在监视的数据发生变化时执行相应的操作。这个回调函数会接收两个参数:新值和旧值,分别表示数据变化后的值和变化前的值。
在这里第一个参数是一个函数,返回我们需要侦听的person.value.age
,第二个参数是一个回调函数,记录坤坤长大的历程...
点击让坤坤长大
看,监听的坤坤的年龄每次更改都会触发watch
computed和watch的区别
经过了上述内容的讲解,我相信聪明的掘友我不说你也知道有什么区别,我们还是来列举一下
-
computed
是一个计算属性,它会根据依赖的响应式数据自动计算出一个新的值,并且只有当依赖的响应式数据发生变化时才会重新计算。而watch是来监听一个响应式数据,当响应式数据发生更新,再去执行一些操作 -
computed
在页面的初次渲染会触发一次,而watch不会,有图有真相
computed
是有缓存的,而watch
默认没有缓存
上面在讲computed和method的区别时举例说明了computed有缓存,这里就不过多赘述,而watch默认是没有缓存的,为什么说是默认呢?因为通过其他方式,可以让watch也具有缓存(设置为第三个参数):
- 使用
{ immediate: true }
:可以在创建watch
时添加该选项,即{ immediate: true }
,这样在初始创建watch
时,回调函数将会立即执行一次,并且会收集依赖关系,之后只有当被监视的数据变化时才会再次执行回调函数。 - 使用
{ flush: 'sync' }
:可以在创建watch
时添加该选项,即{ flush: 'sync' }
,这样回调函数将会在被监视的数据变化时同步地执行,同时也会收集依赖关系。
computed
一定有一个返回值,而watch
不需要
通过上面的例子不难发现,每一个computed都有返回值,而watch没有,因为computed要根据依赖的响应式数据的变更计算出一个新的值,要得到新的值,那就必须返回,而watch是监听一个数据,从而进行某种操作,于是返回值就不是必须的了
5.computed
不能执行异步操作,而 watch
可以
computed
和 watch
的设计初衷和用途不同,这导致它们在处理异步操作上有所区别。computed
的计算过程是同步的,因此在 computed
函数中执行异步操作会导致无法正确缓存计算结果,从而破坏了 computed
的设计初衷。 watch
主要用于监听特定数据的变化,并执行其他操作。在 watch
中,你可以执行包括异步操作在内的任何操作。
结尾
终于是写完了,要是在春招中遇到这个问题,那就偷着乐吧...
假如您也和我一样,在准备春招。欢迎加我微信shunwuyu,这里有几十位一心去大厂的友友可以相互鼓励,分享信息,模拟面试,共读源码,齐刷算法,手撕面经。来吧,友友们!