vue3.x之watchEffect
watchEffect
🔊 官网的介绍
watchEffect方法,它立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。也就是说,我们并不需要传入一个特定的依赖源,而且它会立即执行一遍回调函数,如果函数产生了副作用,那它就会自动追踪副作用的依赖关系,自动分析出响应源。🔉通俗的理解
我们可以把watchEffect方法看成是一个监狱系统,我们传入的的函数就是这个监狱关押囚犯的场地。每一个进入到这个函数内部的响应式变量,就好比是一个个拥有很大能量的罪犯,从这个罪犯进入到监狱场地后,监狱系统就会自动备案及追踪这个拥有大能量罪犯的所有关系网。监狱系统一旦检测到罪犯所属关系网有一点风吹草动,监狱系统就会重新检查一下监狱整个安保体系,以防罪犯策划越狱逃跑。
🌰 举个例子
<template> <div>WatchEffect用法</div><br> <h1>姓名:{{ student.name }}</h1><br> <h1>年龄:{{ student.age }}</h1><br> <button @click="changeReactiveValue">改变信息</button> </template> <script setup lang="ts"> //👀:需要什么导入什么 import { reactive, watchEffect } from 'vue' //1.定义响应式变量 const student = reactive({ name: '铁蛋', age: '1' }) //2.watchEffect侦听 watchEffect(() => { console.log('name:', student.name, 'age:', student.age); }) //3.自定义函数 const changeReactiveValue = function () { student.name = '地瓜' student.age = '2' } </script>
效果:


语法
watchEffect(( ) => { },option?)
参数
watchEffect有两个参数:
第一个参数是在发生变化时要调用的回调函数。
第二个参数是一个可选的选项。有
{flush: 'post'}、{flush: 'sync'}
watchEffect 的 flush 选项用于控制副作用函数的触发时机。flush 选项有三种可能的值:
-
flush: 'pre' 在组件更新前触发(这是默认值)。
默认情况下,watchEffect会在组件更新之前运行副作用函数。这意味着当响应式数据变化时,副作用会在 DOM 更新前执行。 -
flush: 'post' 在组件更新后触发。
将flush设置为'post'可以在组件更新后触发副作用函数。这对于那些需要访问更新后的 DOM 元素的副作用来说很有用。
-
flush: 'sync' 同步地触发。
将flush设置为'sync'可以使副作用同步触发,而不是等到下一个微任务队列。这意味着副作用会立即在响应式数据变化时执行。
import { ref, watchEffect } from 'vue';
const count = ref(0);
// 默认 flush: 'pre'
watchEffect(() => {
console.log(`count (pre): ${count.value}`);
});
// flush: 'post'
watchEffect(() => {
console.log(`count (post): ${count.value}`);
}, { flush: 'post' });
// flush: 'sync'
watchEffect(() => {
console.log(`count (sync): ${count.value}`);
}, { flush: 'sync' });
count.value++;
三个 watchEffect 会在不同的时机记录 count 的值:
flush: 'pre'会在 DOM 更新前执行。flush: 'post'会在 DOM 更新后执行。flush: 'sync'会同步执行。
作用
深度监听响应式变量ref、reactive的数据变化。
watchEffect的使用
watchEffect不需要指明侦听的对象。当侦听的回调中用到哪个属性,就侦听哪个属性。
1. watchEffect侦听ref响应式数据
🐝watchEffect侦听ref定义的一个或多个响应式数据,可以获取preValue
🐝watchEffect侦听ref定义的一个响应式数据的一个或多个属性-基本数据类型,可以获取preValue
🐝watchEffect侦听ref定义的一个响应式数据的一个或多个属性-引用数据类型,可以获取preValue。当没有具体到某个属性时,watchEffect可以侦听引用数据类型的所有属性,也能获取到preValue
🌰示例
<!--text.vue--> <template> <div>test</div> </template> <script setup lang='ts'> import { ref, reactive, watchEffect, onMounted } from 'vue'; // watchEffect侦听reactive响应式数据 // 基本数据类型 const c = ref({ name: 'c', prop: 'prop' }); const d = ref({ name: 'd', prop: 'prop' }); // 引用数据类型 const c1 = ref({ name: 'c1', prop: { name: 'c1', prop: 'prop' } }); const d1 = ref({ name: 'd1', prop: { name: 'd1', prop: 'prop' } }); onMounted(() => { // watchEffect侦听ref数据 c.value.name = 'c-1'; d.value.name = 'd-1'; c1.value.prop.name = 'c1-1'; d1.value.prop.name = 'd1-1'; }); // 1.watchEffect侦听ref定义的一个或多个响应式数据,可以获取preValue watchEffect(() => { // watchEffect不需要指明侦听的对象。当侦听的回调中用到哪个属性,就侦听哪个属性。 console.log(c.value); // {name: 'c', prop: 'prop'} {name: 'c-1', prop: 'prop'} console.log(c.value.name); // c c-1 }); watchEffect(() => { console.log([c.value.name, d.value.name]); // ['c', 'd'] ['c-1', 'd-1'] }); // 2.watchEffect侦听ref定义的一个响应式数据的一个或多个属性-基本数据类型,可以获取preValue watchEffect(() => { console.log(c.value.name); // c c-1 }); watchEffect(() => { console.log([c.value.name, c.value.prop]); // ['c', 'prop'] ['c-1', 'prop'] }); // 3.watchEffect侦听ref定义的一个响应式数据的一个或多个属性-引用数据类型,可以获取preValue // 当具体到引用数据类型的某个属性时,能获取preValue watchEffect(() => { console.log(c1.value.prop.name); // c1 c1-1 }); watchEffect(() => { console.log([c1.value.prop.name, c1.value.prop.prop]); // ['c1','prop'}] ['c1-1','prop'] }); // 当没有具体到某个属性时,可以侦听引用数据类型的所有属性。能获取preValue watchEffect(() => { console.log(c1.value.prop); // {name: 'c1', prop: 'prop'} {name: 'c1-1', prop: 'prop'} }); watchEffect(() => { console.log([c1.value.prop, d1.value.prop]); // [{name: 'c1-1', prop: 'prop'} {name: 'd1-1', prop: 'prop'}] }); </script>
2.watchEffect侦听reactive响应式数据
🦋watchEffect侦听reactive定义的一个或多个响应式数据,可以获取preValue
🦋watchEffect侦听reactive定义的一个响应式数据的一个或多个属性-基本数据类型,可以获取preValue
🦋watchEffect侦听reactive定义的一个响应式数据的一个或多个属性-引用数据类型,可以获取preValue。当没有具体到某个属性时,watchEffect可以侦听引用数据类型的所有属性,也能获取到preValue
🌰示例
<!--text.vue--> <template> <div>test</div> </template> <script setup lang='ts'> import { ref, reactive, watchEffect, onMounted } from 'vue'; // watchEffect侦听reactive响应式数据 // 基本数据类型 const c = reactive({ name: 'c', prop: 'prop' }); const d = reactive({ name: 'd', prop: 'prop' }); // 引用数据类型 const c1 = reactive({ name: 'c1', prop: { name: 'c1', prop: 'prop' } }); const d1 = reactive({ name: 'd1', prop: { name: 'd1', prop: 'prop' } }); onMounted(() => { // watchEffect侦听reactive数据 c.name = 'c-1'; d.name = 'd-1'; c1.prop.name = 'c1-1'; d1.prop.name = 'd1-1'; }); // 1.watchEffect侦听reactive定义的一个或多个响应式数据,可以获取preValue watchEffect(() => { // watchEffect不需要指明侦听的对象。当侦听的回调中用到哪个属性,就侦听哪个属性。 console.log(c); // {name: 'c', prop: 'prop'} {name: 'c-1', prop: 'prop'} console.log(c.name); // c c-1 }); watchEffect(() => { console.log([c.name, d.name]); // ['c', 'd'] ['c-1', 'd-1'] }); // 2.watchEffect侦听reactive定义的一个响应式数据的一个或多个属性-基本数据类型,可以获取preValue watchEffect(() => { console.log(c.name); // c c-1 }); watchEffect(() => { console.log([c.name, c.prop]); // ['c', 'prop'] ['c-1', 'prop'] }); // 3.watchEffect侦听reactive定义的一个响应式数据的一个或多个属性-引用数据类型,可以获取preValue // 当具体到引用数据类型的某个属性时,能获取preValue watchEffect(() => { console.log(c1.prop.name); // c1 c1-1 }); watchEffect(() => { console.log([c1.prop.name, c1.prop.prop]); // ['c1','prop'}] ['c1-1','prop'] }); // 当没有具体到某个属性时,它可以侦听引用数据类型的所有属性,能获取preValue watchEffect(() => { console.log(c1.prop); // {name: 'c1', prop: 'prop'} {name: 'c1-1', prop: 'prop'} }); watchEffect(() => { console.log([c1.prop, d1.prop]); // [{name: 'c1-1', prop: 'prop'} {name: 'd1-1', prop: 'prop'}] }); </script>
📢 注意:
1.当watchEffect侦听引用数据类型时,它可以不需要指明具体的某个属性,便能侦听到该对象的所有属性。
2.watchEffect不需要指明侦听的对象。当侦听的回调中用到哪个属性,就侦听哪个属性。
watchEffect常见用法
1. 基本用法
import { ref, watchEffect } from 'vue';
const count = ref(0);
watchEffect(() => {
console.log(`count: ${count.value}`);
});
2. 取消副作用
import { ref, watchEffect } from 'vue';
const count = ref(0);
const stop = watchEffect(() => {
console.log(`count: ${count.value}`);
});
// 停止副作用
stop();
3. 延迟执行{ flush: 'post' }
import { ref, watchEffect } from 'vue';
const count = ref(0);
watchEffect(() => {
console.log(`count: ${count.value}`);
}, { flush: 'post' });
4. 自定义调度
import { ref, watchEffect } from 'vue';
const count = ref(0);
// 使用 watchEffect 自动追踪副作用
watchEffect(
() => {
// 这个函数在 count 发生变化时会被调用
console.log(`count: ${count.value}`);
},
{
// 配置项:onTrack 和 onTrigger 是调试钩子
// onTrack 会在副作用追踪依赖时调用
onTrack(e) {
console.log('tracked', e);
},
// onTrigger 会在依赖变化导致副作用重新执行时调用
onTrigger(e) {
console.log('triggered', e);
}
}
);
watch和watchEffect
用了一遍watch和watchEffect之后,发现他俩主要有以下几点区别:
1.watch是惰性执行的,而watchEffect不是,不考虑watch第三个配置参数的情况下,watch在组件第一次执行的时候是不会执行的,只有在之后依赖项变化的时候再执行,而watchEffect是在程序执行到此处的时候就会立即执行,而后再响应其依赖变化执行。
2.watch需要传递监听的对象,watchEffect不需要
浙公网安备 33010602011771号