一、前言
-
整理 Vue3 中关于 watch 的几种使用情况
-
watch的参数
// watch的参数说明
watch(要监视的数据,监视的回调 {
//执行的逻辑;
},{配置对象,如deep、immediate);
二、watch的多种使用情况
1、监视ref定义的基本类型数据
1.1 监视value值的改变
-
数据形式如下:
-
监听ref定义的基本类型数据的value值
-
结果
当ref定义的基本类型数据发生改变时,使用上述代码能够检测到变化:
-
完整代码
<template>
<p>小明的年龄是:{{ age }} 岁</p>
<button @click="ageChange">点击年龄加1</button>
</template>
<script setup>
import { ref, watch } from "vue";
// 数据
let age = ref(18);
// 方法
function ageChange() {
age.value += 1;
}
// 监视
watch(age, (newValue, oldValue) => {
console.log("年龄发生变化", newValue, oldValue);
});
</script>
1.2 停止监视
- 监听数据变化的那段代码,本质是一个函数,因此可以将其赋给一个变量,并进行停止监听的操作
- 结果
- 代码
// 停止监视
const stopWatch = watch(age, (newValue, oldValue) => {
console.log("年龄发生变化", newValue, oldValue);
//当年龄大于25时,不再进行监视
if (newValue > 25) {
stopWatch();
}
});
2、监视ref定义的对象类型数据
2.1 监视对象的地址值
-
数据形式如下:
-
若watch的第一个参数直接写数据名,监视的是ref对象的地址值
-
初始结果
-
若单独改变对象的某个属性,是不会发生监视的
-
若改变整个数据,则有监听信息
-
完整代码
<template>
<p>名字:{{ info.name }}</p>
<p>年龄:{{ info.age }} 岁</p>
<p>身高:{{ info.height }} cm</p>
<button @click="ageChange">点击年龄加1</button>
<button @click="heightChange">点击身高加1</button>
<button @click="infoChange">点击更改整体信息</button>
</template>
<script setup>
import { reactive, ref, watch } from "vue";
// 数据
let info = ref({
name: "X先生",
age: 20,
height: 165,
});
// 方法
function ageChange() {
info.value.age += 1;
}
function heightChange() {
info.value.height += 1;
}
function infoChange() {
info.value = {
name: "Y小姐",
age: 30,
height: 178,
};
}
// 监视
watch(info, (newValue, oldValue) => {
console.log("信息变化了", newValue, oldValue);
});
</script>
2.2 监视对象内部的属性
-
当只修改ref定义的对象中的属性,开启深度监听能监听到数据的变化
-
但是输出的newValue和oldValue都是新值,因为他们都是同一个对象
(就好比将房子里面的一件家具,用其他的家具替换,房子还是一样的房子)
-
若想一开始就对数据进行监听,即不管数据有没有变,都执行对应的操作,可以使用{ immediate:true}
-
结果
3、监视reactive定义的对象类型的数据
-
数据形式如下:
-
watch可以监视reactive定义的对象类型的数据,并且默认开启了深度监视,且这种深度监视是不能关闭的:
-
对于reactive 定义的对象类型的数据,不能直接进行整个替换,而应该进行如下操作:
-
结果1:
若修改对象的单个属性,会发生监听,因为watch监视reactive定义的对象类型的数据,默认开启了深度监视
- 结果2:
newValue和oldValue一样,因为对象的地址值没变
4、监视响应式对象的某个属性
监视ref或reactive定义的对象类型数据里的某个数据(而某个数据可以是:基本类型、对象类型)
4.1 属性值不是对象类型
若要监视的属性值是基本类型,比如info里面的name或age或height属性
// 数据
let info = reactive({
name: "X先生",
age: 20,
height: 165,
doll: {
d1: "星黛露",
d2: "玲娜贝儿",
},
});
- 监视的时候,watch的第一个参数要写成函数形式:
- 代码
// 监视对象的基本属性
watch(()=>{return info.name}, (newValue, oldValue) => {
console.log("名字变化了", newValue, oldValue);
});
4.2 若属性值是对象类型
- 若要监视的属性值是对象类型,比如info数据里面的doll属性,可直接写,也可写成函数:
- 直接写,能监视对象的每个属性:
watch(info.doll, (newValue, oldValue) => {
console.log("变化了", newValue, oldValue);
});
-
当对象里面的具体属性发生改变时, 会进行监听,但是整个改变时,没有监听信息:
-
函数形式,只能监听对象的整体情况
watch(
() => info.doll,
(newValue, oldValue) => {
console.log("变化了", newValue, oldValue);
}
);
-
结果:
只能监听对象的整体情况,对象的某个属性发生改变时,没有进行监听
-
函数形式+深度监听:
既能监视对象属性的整体情况,又能监视对象属性里某个值的变化
watch(
() => info.doll,
(newValue, oldValue) => {
console.log("变化了", newValue, oldValue);
},{deep:true}
);
- 结果:
5、监视多个数据
若需要同时监测响应式对象里面的基本类型数据和对象类型数据,需要以数组的形式去监视:
- 要监视的数据如下:
- 代码:
watch(
[() => info.doll.d1, () => info.name],
(newValue, oldValue) => {
console.log("变化了", newValue, oldValue);
},
{ deep: true }
);
- 结果