Vue.js 3 - Composition API使用详解7(watch函数、监听数据变化)
作者:hangge | 2026-05-01 08:49
在 Composition API 中,我们可以使用 watchEffect 和 watch 函数完成响应式数据的监听。其中 watchEffect 函数会自动收集响应式数据的依赖,而 watch 函数则需要手动指定监听数据源。前文我介绍了 watchEffect 的使用,本文接着通过样例演示 watch 函数的使用。
(2)运行效果如下,单击“修改数据”按钮修改 info 中的 name 后,可以看到 watch 已监听到 info 中 name 发生了变化,并打印出了新值和旧值。
(2)如果我们希望 newValue 和 oldValue 是一个普通对象,那么可以采用如下方式监听。在浏览器中单击“修改数据”按钮后,可以看到 watch 已监听到 info 中 name 发生了变化,并打印出了新值和旧值,二者都为普通对象。
(2)在浏览器中单击“修改数据”按钮后,可以看到 watch 已监听到 name 发生了变化,并打印出了新值和旧值,二者都是 name 的 value 值。
(2)单击“修改数据”按钮后,可以看到 watch 已监听到 info.name 和 name 都发生了变化,并打印出了新值和旧值。
(3)在浏览器中刷新页面时,默认立即执行一次 watch 的回调函数。当单击“修改数据”按钮后,可以看到 watch 能够深层监听 info 中 friend 对象的 name 属性发生了变化。
七、watch 函数
1,基本介绍
(1)watch 函数的特点如下:
- 在默认情况下,watch 函数是惰性的,只有当被监听的源发生变化时,才会执行回调函数(副作用函数)。
- watch 函数需要手动指定监听的数据源,而 watchEffect 函数会自动收集响应式数据的依赖。
- watch 函数在副作用函数中可以接收到新值和旧值,而 watchEffect 函数接收不到。
(2)在 Vue.js3 中,watch 函数可以监听两种类型的数据源:
- getter 函数:该函数必须引用响应式对象,如 reactive 或 ref 函数返回的响应式对象。
- 响应式对象:直接接收一个响应式对象,如 reactive 或 ref 函数返回的响应式对象。
2,watch 函数监听的数据源为一个 getter 函数样例
(1)调用 watch 函数监听 info 对象 name 属性的变化。其中,watch 函数需要接收两个参数:
- 第一个参数是一个 getter 函数,该函数必须引用可响应式对象。
- 第二个参数是监听的回调函数,该函数会接收到新值和旧值,并在该函数中打印出新值和旧值。
<template>
<div>
<h4>{{ info.name }}</h4>
<button @click="changeData">修改数据</button>
</div>
</template>
<script>
import { ref, reactive, watch } from 'vue';
export default {
setup() {
const info = reactive({ name: "航歌", age: 88 });
// 侦听watch时,传入一个getter函数
watch(() => info.name, (newValue, oldValue) => {
console.log("newValue:", newValue, "oldValue:", oldValue);
})
const changeData = () => {
info.name = "hangge";
}
return {
changeData,
info
}
}
}
</script>
(2)运行效果如下,单击“修改数据”按钮修改 info 中的 name 后,可以看到 watch 已监听到 info 中 name 发生了变化,并打印出了新值和旧值。

3,watch 函数监听的数据源为 reactive 函数返回的响应式对象样例
(1)下面样例单击“修改数据”按钮后,可以看到 watch 已监听到 info 中 name 发生了变化,并打印出了新值和旧值,二者都为响应式对象。
<template>
<div>
<h4>{{ info.name }}</h4>
<button @click="changeData">修改数据</button>
</div>
</template>
<script>
import { ref, reactive, watch } from 'vue';
export default {
setup() {
const info = reactive({ name: "航歌", age: 88 });
// reactive对象获取到的newValue和oldValue本身都是reactive对象
watch(info, (newValue, oldValue) => {
console.log("newValue:", newValue, "oldValue:", oldValue);
})
const changeData = () => {
info.name = "hangge";
}
return {
changeData,
info
}
}
}
</script>
(2)如果我们希望 newValue 和 oldValue 是一个普通对象,那么可以采用如下方式监听。在浏览器中单击“修改数据”按钮后,可以看到 watch 已监听到 info 中 name 发生了变化,并打印出了新值和旧值,二者都为普通对象。
<template>
<div>
<h4>{{ info.name }}</h4>
<button @click="changeData">修改数据</button>
</div>
</template>
<script>
import { ref, reactive, watch } from 'vue';
export default {
setup() {
const info = reactive({ name: "航歌", age: 88 });
// 如果希望newValue和oldValue是一个普通的对象
watch(() => {
return { ...info }
}, (newValue, oldValue) => {
console.log("newValue:", newValue, "oldValue:", oldValue);
})
const changeData = () => {
info.name = "hangge";
}
return {
changeData,
info
}
}
}
</script>
4,watch 函数监听的数据源为 ref 函数返回的响应式对象样例
(1)样例代码如下:
<template>
<div>
<h4>{{ name }}</h4>
<button @click="changeData">修改数据</button>
</div>
</template>
<script>
import { ref, watch } from 'vue';
export default {
setup() {
// ref对象获取newValue和oldValue是value值的本身
const name = ref("航歌");
watch(name, (newValue, oldValue) => {
console.log("newValue:", newValue, "oldValue:", oldValue);
})
const changeData = () => {
name.value = "hangge";
}
return {
name,
changeData,
}
}
}
</script>
(2)在浏览器中单击“修改数据”按钮后,可以看到 watch 已监听到 name 发生了变化,并打印出了新值和旧值,二者都是 name 的 value 值。

附:进阶技巧
1,监听多个数据源
(1)watch 不仅可以监听单个数据源,还可以通过接收数组实现同时监听多个数据源。下面样例调用 watch 函数监听多个数据源:
- watch 函数的第一个参数接收的是一个数组,该数组中支持监听 getter 函数、ref 和 reactive 函数返回响应式对象的数据源。
- 接着,为 watch 的第二个参数传入回调函数,该回调函数接收的新值和旧值都为数组类型, 然后在该函数中分别打印新值和旧值。
<template>
<div>
<h4>{{ info.name }} - {{ name }}</h4>
<button @click="changeData">修改数据</button>
</div>
</template>
<script>
import { ref, reactive, watch } from 'vue';
export default {
setup() {
// 1.定义可响应式的对象
const info = reactive({ name: "航歌", age: 88 });
const name = ref("百度");
const age = ref(20);
// 2.侦听多数据源,参数一是一个数组:数组中可以有getter函数,ref对象,reactive对象
watch([() => ({ ...info }), name, age],
([newInfo, newName, newAge], [oldInfo, oldName, oldAge]) => {
console.log(newInfo, newName, newAge);
console.log(oldInfo, oldName, oldAge);
})
const changeData = () => {
info.name = "hangge";
name.value = "baidu"
}
return {
changeData,
info,
name
}
}
}
</script>
(2)单击“修改数据”按钮后,可以看到 watch 已监听到 info.name 和 name 都发生了变化,并打印出了新值和旧值。

2,监听响应式对象
(1)如果我们希望监听一个数组或对象,可以使用一个 getter 函数,并对可响应式对象进行解构。下面是一个监听响应式数组的样例:
<template>
<div>
<h4>{{ names }}</h4>
<button @click="changeData">修改数据</button>
</div>
</template>
<script>
import { ref, reactive, watch } from 'vue';
export default {
setup() {
const names = reactive(["hangge", "baidu"]);
// 监听响应式数组
watch(() => [...names], (newValue, oldValue) => {
console.log("newValue:", newValue, "oldValue:", oldValue);
})
const changeData = () => {
names.push("google")
}
return { changeData, names }
}
}
</script>
- 单击“修改数据”后运行效果如下:
(2)如果需要对一个对象进行深度监听,那么可以将 deep 属性设置为 true,也可以传入 immediate 参数立即执行监听函数。下面样例 watch 函数接收了以下三个参数:
- 第一个参数:是一个 geter 函数。
- 第二个参数:是传入的回调函数,在该回调函数中打印接收的新值和旧值。
- 第三个参数“是一个 watch 配置项。
- 如果 deep 为 true,则代表一个深层监听,即当修改了 info 中 friend 对象的 name 时,也会被 watch 监听到;如果为 false,则监听不到。
- immediate 为 true,代表 watch 的回调函数会先立即执行一次,当监听到有数据变化时,才再次执行该回调函数。
<template>
<div>
<h4>{{ info.name }}</h4>
<button @click="changeData">修改数据</button>
</div>
</template>
<script>
import { ref, reactive, watch } from 'vue';
export default {
setup() {
// 1.定义可响应式的对象
const info = reactive({
name: "航歌",
age: 88,
friend: {
name: "baidu"
}
});
// 2.侦听响应式对象
watch(() => ({ ...info }), (newInfo, oldInfo) => {
console.log(newInfo, oldInfo);
}, {
deep: true,
immediate: true
})
const changeData = () => info.friend.name = "google"
return { changeData, info }
}
}
</script>
(3)在浏览器中刷新页面时,默认立即执行一次 watch 的回调函数。当单击“修改数据”按钮后,可以看到 watch 能够深层监听 info 中 friend 对象的 name 属性发生了变化。

全部评论(0)