1️⃣ watch 的使用和几种情况
2️⃣ 情况一:侦听单个 ref 的响应式数据
侦听单个 ref 数据直接作为第一个参数传入
setup() {
let num = ref(100);
watch(
num,
(newValue, oldValue) => {
console.log(`new:${newValue}`);
console.log(`old:${oldValue}`);
},
{ immediate: true }
);
return { num1, num2 };
},
2️⃣ 情况二:侦听多个 ref 的响应式数据
侦听多个 ref 数据时参数为数组模式
setup() {
let num1 = ref(100);
let num2 = ref(200);
watch(
[num1, num2],
(newValue, oldValue) => {
console.log("new", newValue);
console.log("old", oldValue);
},
{ immediate: true }
);
return { num1, num2 };
},
2️⃣ 情况三:侦听 reactive 响应式数据
箭头 reactive 定义的响应式数据
1. 若 watch 侦听的是 reactive 定义的响应式数据,则无法正确获得 oldValue
1. 下面例子中 oldValue 和 newValue 的值是一样的
2. 若 watch 侦听的是 reactive 定义的响应式数据,则强制开启深度侦听
1. 下面例子中更高数据的最深层次依旧可以被 watch 侦听到
3. 原因:可能是因为 reactive 使用的是 proxy 封装的响应式数据,所以 reactive 的数据的 oldValue 和 newValue 是一样的,而 proxy 本身就是深度的,所以在 Vue3 中 watch 侦听 reactive 数据就是深度的
setup() {
let msg = reactive({
num1: 100,
num2: 200,
obj1: {
obj2: {
num3: 300,
},
},
});
watch(
msg,
(newValue, oldValue) => {
console.log("new", newValue);
console.log("old", oldValue);
},
{ immediate: true }
);
return { msg };
},
2️⃣ 情况四:侦听 reactive 响应式数据中的单个非对象数据
侦听 reactive 响应式数据中的单个非对象数据直接作为第一个参数传入
setup() {
let msg = reactive({
num1: 100,
num2: 200,
obj1: {
obj2: {
num3: 300,
},
},
});
watch(
() => msg.num1,
(newValue, oldValue) => {
console.log("new", newValue);
console.log("old", oldValue);
}
);
return { msg };
},
2️⃣ 情况五:侦听 reactive 响应式数据中的单个对象数据
根据情况三的原因,Vue3 中使用的是 proxy 所以 reactive 响应式数据本身就是深度的,但是 proxy 内部的对象并非是 proxy 代理的,所以在侦听 reactive 响应式数据中的单个对象数据时,这单个对象就并非是 proxy 代理的,所以并不会像直接侦听 reactive 数据一样强制开启 deep ,而是需要手动开启才可以深度侦听
setup() {
let msg = reactive({
num1: 100,
num2: 200,
obj1: {
obj2: {
num3: 300,
},
},
});
watch(
() => msg.obj1,
(newValue, oldValue) => {
console.log("new", newValue);
console.log("old", oldValue);
},
{ deep: true }
);
return { msg };
},
2️⃣ 情况六:侦听 reactive 响应式数据中多个非对象数据
侦听 reactive 响应式数据中多个非对象数据时参数为数组模式
setup() {
let msg = reactive({
num1: 100,
num2: 200,
obj1: {
obj2: {
num3: 300,
},
},
});
watch([() => msg.num1, () => msg.num2], (newValue, oldValue) => {
console.log("new", newValue);
console.log("old", oldValue);
});
return { msg };
},
1️⃣ watch 的 value
1️⃣ watchEffect
watchEffect 使用同 watch 一样,不同的是 watchEffect 会默认配置 immediate 为 true,初始执行一次,默认初始时就会执行第一次, 从而可以收集需要监视的数据
watch 的套路是要指明监视的属性,也要指明监视的回调
watchEffect 的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性
watchEffect 有点像 computed:
1. 但 computed 注重的是计算出来的值( 回调函数的返回值 ),所以必须要写返回值
2. 而 watchEffect 更注重的是过程( 回调函数的函数体 ),所以不用写返回值
// watchEffect 所指定的回调中用到的数据只要发生变化 则直接重新执行回调
watchEffect(()=>{
// ......
})
watchEffect 需要注意的是当你侦听一个对象时,即时我们修改了对象中的数据也不会触发 watchEffect ,因为 watchEffect 收集的是对象本身,而非对象的深度侦听,所以使用 watchEffect 时需直接 watchEffect 到值本身。如果我们需要侦听一个对象,推荐使用 watch。<br />一下代码中, watch 可以侦听到,watchEffect 侦听不到。
<template>
<div id="app">
<el-button type="primary" @click="obj.a++">obj.a</el-button>
<el-button type="primary" @click="obj.b.c++">obj.b.c</el-button>
</div>
</template>
<script setup>
import { reactive, watch, watchEffect } from 'vue'
const obj = reactive({
a: 100,
b: {
c: 200
}
})
watch(obj, (newValue, lodValue) => {
console.log('watch', obj);
}, { immediate: true })
watchEffect(() => {
console.log('watchEffect', obj);
})
</script>