一、计算属性
接受一个 getter 函数,并根据 getter 的返回值返回一个不可变的响应式 ref 对象。也就是说,如果我们观察的是
ref或者reactive数据,返回后的数据不能在修改
<template>
<div>{{ plusOne }}</div>
</template>
<script setup>
import { computed } from "vue";
// 定义一个计算属性
const count = ref(1)
const plusOne = computed(() => count.value + 1)
// 但是注意computed返回的数据是不可变数据
// plusOne.value++ // 错误
</script>
如果我们想后面在修改则可以传入 get 和 set 函数的对象可用来创建可写的 ref 对象
<template>
<div>{{ plusOne }}</div>
</template>
<script setup>
import { computed, ref } from "vue";
const count = ref(1)
const plusOne = computed({
/**
* 劫持数据,每次获取的时候,都会自动给数据+1
* 比如 现在template里面的plusOne就是1000
* 注意要有返回值,返回的值就是我们拿到的结果
* 如果说对get不想做操作那么就直接把我们要返回的值返回
*/
get: () => {
return 1000
},
/**
* 每次修改的时候数据-1
* 不需要返回值 这个val就是我们plusOne的值
* 如果说不想劫持则可以直接默认赋值
*/
set: val => {
count.value = val - 1
}
})
plusOne.value += 1
/**
* 这个值是1000,以为我们在劫持了他的数据修改
* 所以我们+1 然后 数据再去件-1,所以相当于没变
*/
console.log(plusOne.value)
</script>
二、watchEffect
为了根据响应式状态自动应用和重新应用副作用,我们可以使用 watchEffect 函数。它立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数,简单来说,我们写的函数,会立即执行一次,然后每次里面的数据发生变化后再出发该函数
<template>
<div>{{ count }}</div>
</template>
<script setup>
import { watchEffect, ref, reactive } from "vue";
const count = ref(1)
const info = reactive({ name: '张三' })
/**
* 创建后会立即执行,然后每次里面使用的响应式数据发生改变的时候
* 注意是响应式数据
* 该函数会再再次执行
*/
watchEffect(() => {
console.log(count.value)
console.log(info.name)
})
setTimeout(() => {
count.value += 1
}, 100)
setTimeout(() => {
info.name = '李四'
}, 2000)
</script>
三、watch
watch用来监听特定的数据源,并在回调函数中执行。
<template>
<div>{{ count }}</div>
</template>
<script setup>
import { watch, ref, reactive } from "vue";
const count = ref(1)
const count2 = ref(2)
const info = reactive({ name: '张三' })
/**
* 监听原始数据类型变化时,可以直接传入
* 数据里面可以跟多个值,有一个值变化就会触发这个方法
* 对应的返回值可以使用数据解构出来
*/
watch([count, count2], ([newVal, newVal2], [oldVal, oldVal2]) => {
console.log(newVal, oldVal)
console.log(newVal2, oldVal2)
})
setTimeout(() => {
count.value += 1
count2.value += 2
}, 1000)
</script>
监听对象类型的数据,并且可以传入第三个参数,是个对象deep 是否深度观察immediate立即执行一次
<template>
<div>哈哈哈</div>
</template>
<script setup>
import { watch, ref, reactive } from "vue";
const info = reactive({ name: '张三' })
const info2 = reactive({ name: '李四' })
/**
* 观察一个或者多个对象的变化,要使用函数的方式返回那个对象
* 如果对象中有属性发生变化就会触发方法
* 注意:watch默认是惰性的,如果观察对象需要手动在第三个参数加{deep: true}
*/
const stop = watch([() => info, () => info2],
([newVal, oldVal], [newVal2, oldVal2]) => {
console.log(newVal, oldVal)
console.log(newVal2, oldVal2)
}, {
deep: true,
immediate: true
})
setTimeout(() => {
info.name = '王五'
info2.name = '王五2'
}, 1000)
// 如果想移除监听则可以拿到watch的返回,并在合适的时候调用它
stop()
</script>
四、watch和watchEffect的区别
1、watchEffect不需要指定监听的属性,自动收集依赖;watch需要指定监听的属性
2、watchEffect拿不到旧值;watch可以拿到旧值
3、watchEffect在组件第一次就会收集依赖,然后收集到的依赖发生了变化,回调才会再次执行;watch就不是了。一开始就指定了依赖。