watch 基本使用
在 Vue3 中的组合式 API 中,watch 的作用和 Vue2 中的 watch 作用是一样的,他们都是用来监听响应式状态发生变化的,当响应式状态发生变化时,都会触发一个回调函数。
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<p>{{ message }}</p>
<button @click="changeMsg">更改 message</button>
</template>
<script setup lang="ts">
import { ref, watch } from "vue";
const message = ref("小猪课堂");
watch(message, (newValue, oldValue) => {
console.log("新的值:", newValue);
console.log("旧的值:", oldValue);
});
const changeMsg = () => {
message.value = "张三";
};
上段代码中我们点击按钮就会更改响应式变量 message 的值。我们又使用 watch 监听器监听了 message 变量,当它发生变化时,就会触发 watch 监听函数中的回调函数,并且回调函数默认接收两个参数:新值和旧值。
注意:当我们第一进入页面时,watch 监听函数的回调函数是不会执行的。
watch 监听类型
前面我们一直强调 watch 监听的是响应式数据,如果我们监听的数据不是响应式的,那么可能会抛出如下警告:
那么哪些数据是属于响应式的,或者换个说法,watch 监听器可以监听哪些形式的数据呢?
ref 和计算属性
ref 定义的数据我们是可以监听到的,因为我们前面的代码以及证明了。除此之外,计算属性也是可以监听到的,比如下列代码:
const message = ref("小猪课堂");
const newMessage = computed(() => {
return message.value;
});
watch(newMessage, (newValue, oldValue) => {
console.log("新的值:", newValue);
console.log("旧的值:", oldValue);
});
当我们 message 发生变化时,计算属性 newMessage 也会重新计算得出新的结果,我们 watch 监听函数是可以监听到计算属性变化的。
getter 函数
这里的 getter 函数大家可以简单的理解为获取数据的一个函数,说白了该函数就是一个返回值的操作,有点类似与计算属性。
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<p>{{ message }}</p>
<p>{{ x1 + x2 }}</p>
<button @click="changeMsg">更改 message</button>
</template>
<script setup lang="ts">
import { ref, watch } from "vue";
const message = ref("小猪课堂");
const x1 = ref(12);
const x2 = ref(13);
watch(
() => x1.value + x2.value,
(newValue, oldValue) => {
console.log("新的值:", newValue);
console.log("旧的值:", oldValue);
}
);
const changeMsg = () => {
message.value = "张三";
x1.value = 14;
x2.value = 23;
};
</script>
上段代码中 watch 监听器中的第一个参数是一个箭头函数,也就是 getter 函数,getter 函数返回的是响应式数据 x1 和 x2 相加的值,当这两个中中有一个变化,都会执行 watch 中的回调函数。有点像是直接把计算属性写到监听器里面去了。
监听响应式对象
前面我们监听的都是值类型的响应式数据,我们同样也可以监听响应式的对象。
const number = reactive({ count: 0 });
const countAdd = () => {
number.count++;
};
watch(number, (newValue, oldValue) => {
console.log("新的值:", newValue);
console.log("旧的值:", oldValue);
});
当 watch 监听的是一个响应式对象时,会隐式地创建一个深层侦听器,即该响应式对象里面的任何属性发生变化,都会触发监听函数中的回调函数。
需要注意的,watch 不能直接监听响应式对象的属性,即下面的写法是错误的:
const number = reactive({ count: 0 });
const countAdd = () => {
number.count++;
};
watch(number.count, (newValue, oldValue) => {
console.log("新的值:", newValue);
console.log("旧的值:", oldValue);
});
上段代码中相当于你直接向 watch 传递了一个非响应式的数字,然而 watch 只能监听响应式数据。
如果我们非要监听响应式对象中的某个属性,我们可以使用 getter 函数的形式,代码如下:
watch(
() => number.count,
(newValue, oldValue) => {
console.log("新的值:", newValue);
console.log("旧的值:", oldValue);
}
);