Vue3 Watch 完全指南:深度监听与性能优化

一、核心概念:Watch 的作用

Watch 用于监听响应式数据的变化并执行副作用操作。与 Computed 不同,Watch 不返回新值,而是响应变化。

javascript

复制代码
import { watch, ref } from 'vue'

const count = ref(0)

watch(count, (newVal, oldVal) => {
  console.log(`从 ${oldVal} 变为 ${newVal}`)
})

二、Reactive vs Ref:关键差异

1. Reactive 对象:默认深度监听

javascript

复制代码
import { reactive, watch } from 'vue'

const user = reactive({ name: '张三', age: 20 })

// ✅ 默认深度监听,修改属性会触发
watch(user, () => {
  console.log('user变化了')  // 修改 user.name 会触发
})

// 等价于显式声明 deep
watch(user, () => {}, { deep: true })

2. Ref 对象:需要显式深度监听

javascript

复制代码
import { ref, watch } from 'vue'

const user = ref({ name: '张三', age: 20 })

// ❌ 修改属性不会触发(只监听引用变化)
watch(user, () => {
  console.log('不会触发')  // user.value.name = '李四' 不会触发
})

// ✅ 需要显式声明 deep
watch(user, () => {
  console.log('会触发')  // 修改属性会触发
}, { deep: true })

三、深度监听的性能问题

深度监听会递归遍历对象的所有属性,性能开销大。

javascript

复制代码
// ❌ 不推荐:深度监听大型对象
const largeObj = reactive({ /* 大量嵌套数据 */ })
watch(largeObj, callback, { deep: true }) // 性能差

// ✅ 推荐:监听特定属性
watch(() => largeObj.importantProp, callback)

// ✅ 推荐:监听多个特定属性
watch(
  () => [largeObj.prop1, largeObj.prop2],
  callback
)

四、实用配置选项

1. immediate:立即执行

javascript

复制代码
const count = ref(0)

watch(count, callback, { 
  immediate: true // 立即执行一次回调
})

2. flush:控制回调时机

javascript

复制代码
watch(source, callback, {
  flush: 'post' // DOM更新后执行,适合操作DOM
})

五、新旧值的陷阱

深度监听时,新旧值引用相同!

javascript

复制代码
const obj = reactive({ a: 1 })

watch(obj, (newVal, oldVal) => {
  console.log(newVal === oldVal) // true!同一个对象
}, { deep: true })

// 解决方案:手动创建副本
watch(
  () => ({ ...obj }),
  (newVal, oldVal) => {
    console.log(newVal === oldVal) // false
  },
  { deep: true }
)

六、最佳实践总结

  1. 监听选择

    • 基本类型:watch(refValue, callback)

    • Reactive对象:watch(reactiveObj, callback)(默认深度)

    • Ref对象:watch(refObj, callback, { deep: true })

  2. 性能优化

    javascript

    复制代码
    // ❌ 避免深度监听大型对象
    watch(largeObj, callback, { deep: true })
    
    // ✅ 监听特定属性
    watch(() => obj.importantField, callback)
    
    // ✅ 计算属性+监听组合
    const importantData = computed(() => obj.a + obj.b)
    watch(importantData, callback)
  3. 清理副作用

    javascript

    复制代码
    const stop = watch(source, callback)
    
    // 组件卸载时清理
    onUnmounted(() => {
      stop()
    })
  4. 使用 watchEffect(自动依赖追踪)

    javascript

    复制代码
    watchEffect(() => {
      // 自动追踪使用的响应式数据
      console.log(obj.name, obj.age)
    })

七、核心要点速记

  • Reactive默认深度,Ref需要显式声明deep

  • 深度监听有性能开销,尽量监听特定属性

  • 深度监听的新旧值是同一引用

  • 合理使用immediate和flush选项

  • 记得清理不再需要的监听器

选择正确的监听策略,可以让你的Vue应用既保持响应性,又拥有优秀的性能表现。

相关推荐
_阿南_2 小时前
项目中新增给AI制定的代码规范
前端·程序员
名字还没想好☜3 小时前
React 实现暗黑模式切换:localStorage 持久化、SSR 首屏闪烁与跟随系统主题
前端·javascript·react.js·ecmascript·react·next.js
自动化监测Learner3 小时前
主流 Web 端地图引擎对比:选型指南与优劣分析
javascript
console.log('npc')4 小时前
Git 冲突与 AI 协助指南
前端·人工智能·git·大模型
爱学堂IT分享5 小时前
Cesium可视化系统实战课程-Cesium教程学习
前端
糖墨夕5 小时前
理解大语言模型:Agent 的“大脑”
前端·agent
Rain的Java大神之路5 小时前
JavaWeb开发如何解决跨域问题
java·前端·后端·nginx·web安全·面试·运维开发
cpolar技术支持6 小时前
浏览器也能跑本地 AI:用 Transformers.js + WebGPU 做一个最小推理 Demo,cpolar 给同事远程体验
前端·ai·cpolar·webgpu·transformers.js
计算机毕设定制辅导-无忧学长6 小时前
《基于SpringBoot青年公寓出租管理系统的设计与实现》
java·vue.js·spring boot·青年公寓出租管理系统
计算机魔术师7 小时前
OpenAI 发布 GPT-6 Astra:多项基准刷新纪录, cybersecurity 能力达 Critical 阈值
前端