学习笔记--vue3 watch监听的各种姿势用法和总结

在 Vue 3 中,watch 监听不同数据源的方式有所不同

1. 监听单个 ref

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

const count = ref(0)

// 直接传入 ref
watch(count, (newVal, oldVal) => {
  console.log('count 变化:', newVal, oldVal)
})

// 或者使用 getter 函数
watch(() => count.value, (newVal, oldVal) => {
  console.log('count 变化:', newVal, oldVal)
})

2. 监听多个 ref

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

const count = ref(0)
const name = ref('John')

// 方式1:使用数组
watch([count, name], ([newCount, newName], [oldCount, oldName]) => {
  console.log('count 变化:', newCount, oldCount)
  console.log('name 变化:', newName, oldName)
})

// 方式2:使用 getter 数组
watch(
  [() => count.value, () => name.value],
  ([newCount, newName], [oldCount, oldName]) => {
    console.log('多个数据变化')
  }
)

3. 监听单个 reactive

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

const state = reactive({
  count: 0,
  name: 'John'
})

// ❌ 错误:直接传入 reactive 对象无法监听到内部属性的变化
watch(state, (newVal, oldVal) => {
  console.log('不会触发') // 深度监听时才会触发
})

// ✅ 正确:使用 getter 函数监听特定属性
watch(
  () => state.count,
  (newVal, oldVal) => {
    console.log('count 变化:', newVal, oldVal)
  }
)

// ✅ 深度监听整个 reactive 对象
watch(
  () => state,
  (newVal, oldVal) => {
    console.log('state 任何属性变化都会触发')
  },
  { deep: true }
)

4. 监听多个 reactive 数据

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

const state1 = reactive({ count: 0 })
const state2 = reactive({ name: 'John' })

// 方式1:使用 getter 数组
watch(
  [() => state1.count, () => state2.name],
  ([newCount, newName], [oldCount, oldName]) => {
    console.log('数据变化')
  }
)

// 方式2:深度监听整个 reactive 对象(不推荐)
watch(
  [() => state1, () => state2],
  ([newState1, newState2], [oldState1, oldState2]) => {
    // 注意:oldState1 和 newState1 指向同一个对象
    console.log('状态变化')
  },
  { deep: true }
)

5. 混合监听 ref 和 reactive

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

const count = ref(0)
const state = reactive({ name: 'John', age: 18 })

watch(
  [count, () => state.name, () => state.age],
  ([newCount, newName, newAge], [oldCount, oldName, oldAge]) => {
    console.log('混合数据变化')
  }
)

6. 监听响应式对象的属性

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

const user = reactive({
  info: {
    name: 'John',
    address: {
      city: 'Beijing'
    }
  }
})

// 监听嵌套属性
watch(
  () => user.info.address.city,
  (newVal, oldVal) => {
    console.log('城市变化:', newVal, oldVal)
  }
)

// 深度监听整个对象
watch(
  () => user,
  (newVal, oldVal) => {
    console.log('user 任何变化')
  },
  { deep: true }
)

总结对比

数据源 监听方式 注意事项
单个 ref watch(count, callback) 直接传入即可
多个 ref watch([ref1, ref2], callback) 使用数组形式
单个 reactive 属性 watch(() => state.prop, callback) 必须使用 getter
多个 reactive 属性 watch([() => state.prop1, () => state.prop2], callback) 使用 getter 数组
整个 reactive watch(() => state, callback, { deep: true }) 必须深度监听

最佳实践建议

  1. 优先使用 getter 函数,特别是监听 reactive 对象的属性
  2. 避免深度监听大型对象,可能会影响性能
  3. 注意旧值的引用问题:对于 reactive 对象,旧值可能与新值相同(因为引用未变)
相关推荐
岁岁种桃花儿8 分钟前
Vue核心语法第一篇:Vue是什么?
前端·javascript·vue.js
观无1 小时前
若依EasyExcel实现单元格合并
开发语言·前端·javascript
愚公搬代码1 小时前
【愚公系列】《Web应用安全》001-VMware的安装
前端·安全
xiaohaiAIgeo1 小时前
【2026年】HG/T 20656-2024化工暖通空调设计规范:新版标准的变化与影响
java·前端·javascript·科普知识
立少→万能汉编1 小时前
用“立少→超文本”写静态网页,标签<倍>
服务器·前端·javascript
weixin_431600441 小时前
NestJS 入门(7):生命周期钩子——构造函数和 `OnModuleInit` 差在哪?
前端·后端·学习·node.js·nest.js
你挚爱的强哥2 小时前
【chromeDownload】自定义组件:多用于登录框底部提供下载Chrome谷歌浏览器的链接
前端·vue.js·chrome
cindershade2 小时前
用原生 HTML5 视频与 Canvas 实现浏览器端视频抽帧封面
前端
笨鸟先飞,勤能补拙2 小时前
Web 服务器与计算机网络全景原理
运维·服务器·前端·网络·人工智能·计算机网络·web安全
NutShell Wang2 小时前
Wails v3 Beta 实战:用显式对象模型重写你的第一个 Go 桌面应用
前端·人工智能·go·vibe coding