深入理解 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 中最强大的响应式工具之一,但也最容易被误用。理解它的"立即执行"、"依赖追踪"和"清理机制",才能用好它!

相关推荐
陪我一起学编程31 分钟前
创建Vue项目的不同方式及项目规范化配置
前端·javascript·vue.js·git·elementui·axios·企业规范
LinXunFeng1 小时前
Flutter - 详情页初始锚点与优化
前端·flutter·开源
GISer_Jing1 小时前
Vue Teleport 原理解析与React Portal、 Fragment 组件
前端·vue.js·react.js
Summer不秃1 小时前
uniapp 手写签名组件开发全攻略
前端·javascript·vue.js·微信小程序·小程序·html
coderklaus2 小时前
Base64编码详解
前端·javascript
NobodyDJ2 小时前
Vue3 响应式大对比:ref vs reactive,到底该怎么选?
前端·vue.js·面试
xianxin_2 小时前
CSS Visibility(可见性)
前端
朱程2 小时前
写给自己的 LangChain 开发教程(二):格式化数据 & 提取 & 分类
前端·人工智能
小喷友2 小时前
第5章 高级UI与动画
前端·app·harmonyos
笃行3502 小时前
【实用部署教程】olmOCR智能PDF文本提取系统:从安装到可视化界面实现
前端