Watch
watch只能监听响应式数据(ref reactive...) ,监听多个响应式数据用数组表示
第一个参数要监听的响应式数据或者一个带返回值的函数
但是如果我需要监听dataObj这个响应式对象的age属性变化,这么写能成功监听吗?
const dataObj = reactive({ age: 1 });
function add() {
dataObj.age++;
}
watch(dataObj.age, (newVal, oldVal) => {
console.log(newVal, oldVal, "age");
});
显然是不行的,因为watch只能监听响应式数据,dataObj.age就只是一个普通的值了
两种办法:
- 使用
toRef变成响应式数据
watch(toRef(dataObj, "age"), (newVal, oldVal) => {
console.log(newVal, oldVal, "age");
});
- 将它作为函数返回
()=>dataObj.age
watch(
() => dataObj.age,
(newVal, oldVal) => {
console.log(newVal, oldVal, "age");
}
);
第二个参数是在发生变化时要调用的回调函数。
这个回调函数接受三个参数:新值、旧值,以及一个用于注册副作用清理的回调函数。
第三个可选的参数是一个配置对象
immediate
在侦听器创建时立即触发回调。第一次调用时旧值是 undefined。
deep使用场景(很少使用)
如果是以ref修饰的对象,修改这个响应式对象内的属性是监听不到的,举个例子
<template>
<div>
<p>Original Object: {{ originalObject }}</p>
<button @click="updateValue">Update Value</button>
</div>
</template>
<script setup>
import { ref, watch } from 'vue';
const originalObject = ref({
data: 'Initial Value'
});
// 不使用 deep 选项
watch(originalObject, (newVal, oldVal) => {
console.log('Without deep:', newVal, oldVal);
});
// 使用 deep 选项
watch(originalObject, (newVal, oldVal) => {
console.log('With deep:', newVal, oldVal);
}, { deep: true });
function updateValue() {
originalObject.value.data = 'Updated Value';
}
</script>
点击按钮会修改originalObject里的属性,打印如下
可以看到只有deep为true时,才能监听到originalObject内属性变化
flush
首先要知道watch的回调默认在组件更新之前被调用,flush的属性默认是pre,举个例子
<template>
<div class="main-component">
<div ref="divRef" class="count-display">{{ count }}</div>
<button class="add-button" @click="add">+1</button>
</div>
</template>
<script setup>
import { ref, watch } from "vue";
const count = ref(1);
const divRef = ref(null);
function add() {
count.value++;
}
watch(
count,
(newVal, oldVal) => {
console.log(divRef.value.textContent, "age");
console.log(oldVal, "oldVal");
console.log(newVal, "newVal");
},
{
flush: "pre",
}
);
</script>
watch时通过ref拿到DOM的内容,点击+1,打印
可以看出拿到的DOM的内容与count的旧值相同
这是因为watch的副作用函数在组件更新前执行,这个时候拿到的数据是还没有更新的值
怎么才能拿到最新的值呢,只需要将flush属性设置为post
watchEffect
watchEffect会自动跟踪回调中使用到的响应式数据。也就是不需要单独指定追踪哪个响应式数据,它会帮助我们智能的收集起来
与watch相同他也有flush属性,没有immediate,但是相当于immediate:true.也没有deep
watch watchEffct默认都可以进行深度监听,但是如果只需要监听其中的几个属性,使用watchEffect更好,因为它将只跟踪回调中被使用到的属性,而不是递归地跟踪所有的属性。
如果你需要新旧值,只能使用watch,但是watch监听一个响应式对象,此时新值和旧值是相同的,想拿到不同的这么写就可以了
watch(
() => {
return { ...dataObj };
},//之前是直接写dataObj
(newVal, oldVal) => {
console.log(oldVal, "age");
console.log(newVal, "age");
},
);
销毁监听器
这两种都是一样的,都会返回一个函数unwatch,再次执行这个函数就会销毁监听器
const unwatch = watchEffect(() => {})
unwatch()//销毁