学习笔记--vue3 watch监听的各种姿势用法和总结
作者:互联网
2026-03-26
在 Vue 3 中,watch 不同数据源的方式有所不同
1. 单个 ref
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
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
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 数据
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
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. 响应式对象的属性
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 }) | 必须深度 |
最佳实践建议
- 优先使用 getter 函数,特别是 reactive 对象的属性
- 避免深度大型对象,可能会影响性能
- 注意旧值的引用问题:对于 reactive 对象,旧值可能与新值相同(因为引用未变)
相关推荐
专题
+ 收藏
+ 收藏
+ 收藏
+ 收藏
+ 收藏
最新数据
相关文章
最新版vue3+TypeScript开发入门到实战教程之路由详解二
03/28
src-components调用链与即时聊天组件树
03/28
从0开始设计一个树和扁平数组的双向同步方案
03/28
拒绝 rem 计算!Vue3 大屏适配,我用 vfit 一行代码搞定
03/28
Home双router-view与布局切换逻辑
03/28
uniapp uview-plus 自定义动态验证
03/28
Vue3 单元测试实战:从组合式函数到组件
03/28
VUE-组件命名与注册机制
03/28
VTJ.PRO 在线应用开发平台概览
03/28
v0.dev 支持 RSC 了!AI 生成全栈组件离我们还有多远?
03/28
AI精选
