watcheffect在vue 3中自动追踪响应式依赖并立即执行,支持防竞态清理、dom更新后执行及手动停止。

在 Vue 3 单文件组件(SFC)中使用 watchEffect 很直接:它会自动读取函数体内访问的响应式变量,并在这些变量变化时重新执行整个函数,且首次定义就立即运行。
基础写法:一行监听,无需声明依赖
在 <script setup></script> 中,导入后直接调用即可:
import { ref, watchEffect } from 'vue'
const count = ref(0)
const name = ref('Alice')
watchEffect(() => {
console.log('count:', count.value, 'name:', name.value)
})
只要 count.value 或 name.value 被修改,回调就会重新执行。没被读取的响应式属性,哪怕在同一对象里,也不会触发更新。
处理异步请求:防竞态与自动清理
发起 API 请求时,旧请求可能未完成就被新请求覆盖。用 onInvalidate 清理上一次副作用:
const url = ref('/api/data')
const data = ref(null)
const loading = ref(false)
watchEffect((onInvalidate) => {
loading.value = true
const controller = new AbortController()
onInvalidate(() => controller.abort())
fetch(url.value, { signal: controller.signal })
.then(res => res.json())
.then(json => data.value = json)
.finally(() => loading.value = false)
})
- 每次
url.value改变,都会新建AbortController并注册清理 - 上一次请求若还在 pending,
onInvalidate会提前中止它 - 组件卸载时也会自动触发清理,避免内存泄漏
控制执行时机:适配 DOM 更新节奏
默认在组件更新前执行(flush: 'pre')。若需操作真实 DOM(比如读取元素尺寸),改用 flush: 'post':
watchEffect(() => {
const el = document.querySelector('#my-box')
if (el) console.log('高度:', el.offsetHeight)
}, { flush: 'post' })
这样能确保 DOM 已完成渲染,拿到的是最新尺寸。
手动停止监听:组件级生命周期管理
返回值是一个停止函数,适合在组件卸载时调用:
const stop = watchEffect(() => {
console.log('监听中...')
})
// 组件卸载前停止(例如 onBeforeUnmount)
onBeforeUnmount(() => stop())
不手动停止也没问题——Vue 在组件销毁时会自动清理,但显式调用更清晰、更可控。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










