一文读懂Vue3 Watch:轻松掌握前端开发新技能!_回调函数

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 监听函数的回调函数是不会执行的。

一文读懂Vue3 Watch:轻松掌握前端开发新技能!_回调函数_02

watch 监听类型

前面我们一直强调 watch 监听的是响应式数据,如果我们监听的数据不是响应式的,那么可能会抛出如下警告:

一文读懂Vue3 Watch:轻松掌握前端开发新技能!_响应式_03

那么哪些数据是属于响应式的,或者换个说法,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>

一文读懂Vue3 Watch:轻松掌握前端开发新技能!_数据_04

上段代码中 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);
});

一文读懂Vue3 Watch:轻松掌握前端开发新技能!_回调函数_05

当 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);
  }
);