深入理解 Vue 3 中的 watchEffect

深入理解 Vue 3 中的 watchEffect:执行时机、陷阱与性能优化

一、watchEffect 是什么?

在 Vue 3 中,watchEffect 是组合式 API 中用于自动收集依赖并响应变化的副作用函数 。它在响应式依赖变动时重新运行,类似于 computed 的"副作用版"。

相比传统的 watch,它更自动、代码更简洁。


二、基本用法回顾

javascript 复制代码
import { ref, watchEffect } from 'vue'
​
const count = ref(0)
​
watchEffect(() => {
  console.log('count is:', count.value)
})

这段代码会:

  • 立即执行一次
  • 依赖收集 count
  • 当 count 变化时自动重新运行

三、关键难点:执行时机 & 执行机制

执行时机:

默认情况下,watchEffect 是在组件渲染前同步执行,但也可以通过选项控制:

arduino 复制代码
watchEffect(() => {
  console.log('DOM 渲染前执行')
}, {
  flush: 'pre' // 默认值
})

其他选项:

flush 类型 执行时机 使用场景
'pre' 渲染前(默认) 需要在 DOM 更新前读取状态
'post' 渲染后(DOM 更新后) 依赖 DOM 或使用 $el
'sync' 立即同步执行 依赖顺序执行或数据推送场景
scss 复制代码
watchEffect(() => {
  console.log(el.value?.offsetHeight)
}, {
  flush: 'post'
})

四、常见陷阱

1. 非响应式变量不会触发重新执行

javascript 复制代码
let name = 'Tom'
​
watchEffect(() => {
  console.log(name) // 这不是响应式变量
})

解决方法:使用 refreactive


2. 非主动使用 .value 的响应式变量不会被追踪

scss 复制代码
const user = ref({ name: 'Tom' })
​
watchEffect(() => {
  console.log(user.value) // 会触发
  // console.log(user.value.name) // 也会触发
  // 但如果只访问 user 而不访问 .value,无法追踪
})

3. 副作用函数里有异步操作要清理

javascript 复制代码
watchEffect((onCleanup) => {
  const timer = setInterval(() => {
    console.log('轮询')
  }, 1000)
​
  onCleanup(() => {
    clearInterval(timer)
  })
})

如果不清理副作用,组件卸载或数据切换时可能导致内存泄漏或逻辑冲突


五、性能优化建议

1.避免在 watchEffect 内执行复杂逻辑

scss 复制代码
watchEffect(() => {
  // 慎用:大量计算、循环、DOM 查询
  for (let i = 0; i < 10000; i++) { ... }
})

拆分逻辑改用 watch + debounce 更合适


2. 需要精确控制依赖时,优先使用 watch

javascript 复制代码
watch(() => someReactive.value, (newVal) => {
  // 更精细的控制
})

六、实践 Demo:表单自动保存

xml 复制代码
<script setup>
import { ref, watchEffect } from 'vue'

const form = ref({ title: '', content: '' })

watchEffect(() => {
  if (form.value.title || form.value.content) {
    localStorage.setItem('draft', JSON.stringify(form.value))
  }
})
</script>

<template>
  <input v-model="form.title" placeholder="标题" />
  <textarea v-model="form.content" placeholder="内容" />
</template>

自动保存草稿,用户刷新不会丢失。


七、总结:何时使用 watchEffect

使用时机 推荐工具
自动依赖追踪、副作用立即执行 watchEffect
精确监听某个属性并节流或控制频率 watch
不需要副作用,只计算依赖结果 computed

八、源码解析拓展(进阶)

在 Vue 3 中,watchEffect 实际通过 effect() 实现响应式副作用收集,并通过 scheduler 控制重新执行时机。

源码文件位置:packages/reactivity/src/effect.ts

核心关键代码(简化版):

javascript 复制代码
function watchEffect(fn, options) {
  const runner = effect(fn, {
    scheduler: queueJob, // 控制刷新节奏
    ...options
  })
}

总结:

watchEffect 是 Composition API 中最强大的响应式工具之一,但也最容易被误用。理解它的"立即执行"、"依赖追踪"和"清理机制",才能用好它!

相关推荐
jingchao19985 分钟前
Cannot read properties of null (reading ‘insertBefore‘)
前端·javascript·vue.js
计算机魔术师9 分钟前
新文章
前端
爱跳舞的烤冷面12 分钟前
自学嵌入式第N天(Linux篇——文件编程)
java·开发语言·前端
IT_陈寒18 分钟前
Vite的热更新突然失效,原来我忽略了这个配置
前端·人工智能·后端
怪奇云呼军20 分钟前
闪电智能VoiceAgent 如何管理呼入、接听、桥接和挂断状态?
java·前端·网络·数据库·人工智能
云浪22 分钟前
Milvus + RAG 实战:《红楼梦》问答助手
前端·人工智能·后端
恋猫de小郭40 分钟前
Dart 3.13 大更新,感觉比 Flutter 更带劲
android·前端·flutter
晓得迷路了41 分钟前
栗子前端技术周刊第 142 期 - DeepSeek Harness、pnpm 12 RC、crypto‑js...
前端·javascript·ai编程
xiaoxiangsiyan1 小时前
RHCE之2026年全套考点详解
运维·前端·网络·chrome·学习·rhce
Fluxart.ai1 小时前
Etsy手工制品换背景,用什么AI能保留手作质感?
前端·javascript·人工智能