一文详解Vue3中watch的使用方法、写法及应用场景
引言
在 Vue 3 的组合式 API(Composition API)中,watch 是一个非常核心且强大的工具,用于监听响应式数据的变化并执行相应的副作用操作。本文将结合实际代码示例,深入讲解 watch 的使用方法、参数配置(如 deep、immediate)、常见写法及其应用场景。
一、watch 基本用法
Vue 3 中的 watch 函数用于监听响应式引用(ref)、响应式对象(reactive)或计算属性(computed)的变化。其基本语法如下:
import { watch } from 'vue'
watch(source, callback, options?)- source:要监听的数据源,可以是 ref、reactive 对象、getter 函数,或由多个上述组成的数组。
- callback:当监听的数据发生变化时触发的回调函数,接收新值和旧值作为参数。
- options(可选):配置选项,如
{ deep: true, immediate: true }。
二、常见写法与示例分析
1. 监听 ref 或 reactive 对象
const count = ref(0)
watch(count, (newVal, oldVal) => {
console.log(`count 从 ${oldVal} 变为 ${newVal}`)
})对于 reactive 对象,若只监听整个对象(而非深层属性),默认不会触发深层监听:
const user = reactive({ name: 'Alice', age: 25 })
// ❌ 这样不会监听到 user.name 的变化!
watch(user, (newVal, oldVal) => {
// 不会触发
})此时需要开启 deep: true(见下文)。
2. 使用 getter 函数监听特定属性(推荐方式)
这是最灵活、最常用的方式,尤其适用于监听 props、route 等非直接 ref 的数据。
示例 1:监听 props 中的复杂对象(如数组)
watch(
() => props.fileList,
(newFiles, oldFiles) => handleFiles(newFiles, oldFiles),
{ deep: true }
)() => props.fileList:返回一个 getter 函数,确保能正确追踪依赖。deep: true:因为fileList很可能是数组或对象,内部元素变化不会触发浅层监听,必须开启深度监听。- 回调函数接收新旧值,便于做差异处理(如上传文件列表变更)。
注意:如果 fileList 是一个数组,即使你 push 一个新文件,浅层监听也不会触发,因为数组引用未变。deep: true 能解决这个问题。
示例 2:监听路由路径变化
watch(
() => route.path,
(newPath) => {
activeMenu.value = newPath
}
)route来自vue-router的useRoute(),是一个响应式对象。- 监听
route.path可以在用户切换页面时自动更新高亮菜单项。 - 此处无需
deep,因为path是字符串(原始值),变化即触发。
三、关键配置选项详解
1.deep: true—— 深度监听
- 作用:监听对象或数组内部属性的变化。
- 适用场景:监听嵌套对象、数组、props 中的复杂结构。
- 注意:性能开销较大,仅在必要时使用。
const form = reactive({
user: { name: '', email: '' }
})
watch(form, (newVal) => {
// 默认不触发
}, { deep: true }) // 开启后,user.name 变化也会触发对于 ref 包裹的对象,watch(refObj, ..., { deep: true }) 也能深度监听。
2.immediate: true—— 立即执行
- 作用:在侦 听器创建时立即执行一次回调。
- 适用场景:初始化时就需要根据当前值执行逻辑(如根据路由加载数据)。
watch(
() => route.query.id,
(id) => {
if (id) fetchDetail(id)
},
{ immediate: true }
)如果不加 immediate: true,首次进入页面时 id 存在但不会触发 fetchDetail。
3. 同时监听多个源
watch([refA, refB], ([newA, newB], [oldA, oldB]) => {
console.log('A or B changed')
})四、watch vs watchEffect
| 特性 | watch | watchEffect |
|---|---|---|
| 是否需要指定依赖 | ✅ 需要显式指定 | ❌ 自动追踪 |
| 能否访问旧值 | ✅ 可以 | ❌ 不能 |
| 是否立即执行 | 默认否(可用 immediate 控制) | ✅ 总是立即执行 |
| 适用场景 | 需要对比新旧值、精确控制依赖 | 初始化 + 自动依赖追踪 |
通常建议优先使用 watch,因为它更明确、可控。
五、最佳实践建议
- 监听 props 时,始终使用 getter 写法:
() => props.xxx - 对对象/数组变化,记得加
deep: true - 需要初始化执行?加
immediate: true - 避免在 watch 中修改被监听的值,可能引发无限循环
- 及时清理副作用(如取消请求),可在回调中返回清理函数(类似 useEffect)
watch(someRef, async (id) => {
const cancelToken = axios.CancelToken.source()
try {
await axios.get(`/api/data/${id}`, { cancelToken: cancelToken.token })
} catch (e) {
if (!axios.isCancel(e)) throw e
}
// 返回清理函数
return () => cancelToken.cancel()
})六、总结
watch 是 Vue 3 组合式 API 中处理副作用和响应式数据联动的核心工具。通过合理使用 deep、immediate 等选项,我们可以精准控制监听行为,提升应用的响应性和用户体验。
以上就是一文详解Vue3中watch的使用方法、写法及应用场景的详细内容,更多关于Vue3 watch使用方法的资料请关注脚本之家其它相关文章!
相关文章
Vue2.0使用嵌套路由实现页面内容切换/公用一级菜单控制页面内容切换(推荐)
这篇文章主要介绍了Vue2.0使用嵌套路由实现页面内容切换/公用一级菜单控制页面内容切换,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下2019-05-05
Vue3 $emit用法指南(含选项API、组合API及 setup 语法糖)
这篇文章主要介绍了Vue3 $emit用法指南,使用 emit,我们可以触发事件并将数据传递到组件的层次结构中,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下2022-07-07


最新评论