相同点
都是要根据一个或多个响应式
数据进行监听
不同点
- computed 如要return回来一个新的响应式值,且这个值不允许直接修改,想要修改的话可以设置
set
函数,在函数里面去修改所依赖的响应式
数据,然后计算属性值会基于其响应式依赖被缓存
- watch 监听一个或多个
响应式
数据,当数据发生变化的时候可以去做一些修改其他值
,执行异步操作,如发送求情
,修改dom
,然后watch默认是懒侦听的,也就是说刚进入页面的时候不会触发,仅在侦听源发生变化的时候才会执行回调函数,这个时候我们可以设置immediate
为true,这表示在侦听器创建时立即触发回调,如果侦听源是对象,我们想做深层次侦听我们需要设置deep
为true
computed
- 接受一个
getter函数
,返回一个只读
的响应式ref
对象该ref
对象通过.value
暴漏getter函数的返回值
<script setup lang="ts">
const a = ref('小明');
const b = ref('小红');
const c = computed(() => `${a.value}_${b.value}`);
</script>
<template>
{{ c }}
</template>
这个时候页面上会显示 小明_小红
这个时候也不知道有了个什么样的需求,我想要给c
赋值,如c.value = 小花
可以看到是不行的,因为这个时候computed
返回的只是一个只读的ref,接着往下看
<script setup lang="ts">
const a = ref('小明');
const b = ref('小红');
const c = computed({
get() {
return `${a.value}_${b.value}`;
},
set(val) {
console.log(val);
},
});
const changeC = () => {
c.value = '小花';
};
</script>
<template>
{{ c }}
<a-button @click="changeC">改变C</a-button>
</template>
这个时候点击按钮后,可以看到控制台会输出小花
,这个时候你可以做一些操作比如
这个时候页面上就会展示
- vue的计算属性会自动追踪
响应式
依赖,它会检测到c
依赖于a
,b
,也就是说当a
或者b
改变时,c
就会同时更新 计算属性值会基于其响应式依赖被缓存
一个计算属性仅在其响应式依赖更新时才重新计算,这意味着a
或b
不改变,无论访问c
多少次都会立即返回先前计算的结果,而不用重复执行getter函数- getter不应有副作用,也就是说不要在计算属性里面去改变其他状态,不要在getter中去做异步请求以及改变dom,如果有这种需求则要到watch去操作
- 避免直接修改计算属性值,如果想要修改计算属性的值,应该去更新它所依赖的响应式字段,也就是说我们想要改变
c
那么我们应该想的是如何去改变a
和b
watch
侦听一个或多个响应式
数据源,并在数据变化
时调用所给的回调函数
const x = ref(0)
const y = ref(0)
// 单个 ref
watch(x, (newX) => {
console.log(`x is ${newX}`)
})
// getter 函数
watch(
() => x.value + y.value,
(sum) => {
console.log(`sum of x + y is: ${sum}`)
}
)
// 多个来源组成的数组
watch([x, () => y.value], ([newX, newY]) => {
console.log(`x is ${newX} and y is ${newY}`)
})
如果有以下需求
要是用
<script setup lang="ts">
const obj = reactive({
count: 0,
});
watch(
// 提供一个getter函数
() => obj.count,
count => {
console.log('做一些操作');
}
);
</script>
watchEffect
我的理解就是,比如说我们要监听一个id
发生变化的时候,我们要去请求一个接口获取详情
用watch
的写法
const todoId = ref(1)
const data = ref(null)
watch(
todoId,
async () => {
const response = await fetch(
`https://jsonplaceholder.typicode.com/todos/${todoId.value}`
)
data.value = await response.json()
},
{ immediate: true }
)
我们需要监听todoId
,然后…
现在如果使用watchEffect
,可以这样写
watchEffect(async () => {
const response = await fetch(
// 逻辑里面必须要有todoId的使用,否则todoId变化了,也不会监听
`https://jsonplaceholder.typicode.com/todos/${todoId.value}`
)
data.value = await response.json()
})