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应用既保持响应性,又拥有优秀的性能表现。

相关推荐
yuanyxh10 小时前
Mac 软件推荐
前端·javascript·程序员
万少10 小时前
AtomCode开发微信小程序《谁去呀》 全流程
前端·javascript·后端
某人辛木11 小时前
Web自动化测试
前端·python·pycharm·pytest
Kagol11 小时前
Superpowers GSD gstack AgentSkills深度测评
前端·人工智能
excel12 小时前
JavaScript 字符串与模板字面量:从表象到本质理解
前端
京东云开发者12 小时前
当AI成为导演-如何用AI创作动漫短剧
前端
李白的天不白13 小时前
使用 SmartAdmin 进行前后端开发
java·前端
乘风gg13 小时前
🤡PUA AI Coding 工具 的 10 条终极语录
前端·ai编程·claude
学Linux的语莫13 小时前
Vue 3 入门教程
前端·javascript·vue.js
怕浪猫14 小时前
第一章、Chrome DevTools Protocol (CDP) 详解
前端·javascript·chrome