Vue watch 回调可同时获取新旧值,但准确性取决于监听目标与配置:ref/计算属性直接提供;reactive 需 deep:true 捕获深层变化;多数据源宜用 computed 聚合后监听;数组或对象浅层变更需特殊处理。

Vue 的 watch 回调天然支持接收新旧值,但能否“同时获取”并“准确对比”,取决于你监听的是什么、怎么监听、以及是否配置得当。
监听 ref 或计算属性:新旧值直接可用
当你 watch 一个 ref(如 count = ref(0))或一个返回响应式值的 getter(如 () => user.name),回调函数会自动传入两个参数:
- 第一个是变更后的新值(
newValue) - 第二个是变更前的旧值(
oldValue) - 首次触发时(尤其加了
{ immediate: true }),oldValue为undefined,需手动判断
监听 reactive 对象:默认只看引用,深层变化要 deep
直接 watch 一个 reactive({ name: 'a', profile: { age: 25 } }),默认只在对象被整体替换时才触发,user.profile.age = 26 不会触发回调——因为引用没变。
想捕获内部字段变化,必须启用深度监听:
- 配置
{ deep: true } - 此时
newValue和oldValue仍是整个对象,但它们是响应式代理的快照(非原始引用) - 注意:
oldValue在首次 deep 监听中也可能为undefined,尤其配合immediate时 - 避免无差别 deep 监听大对象;推荐先用
computed提取关键字段再 watch
监听多个数据源:聚合后 watch,结构更可控
不要为 keyword、status、page 各写一个 watch。统一用 computed 包装成对象再监听:
- 定义
const searchParams = computed(() => ({ keyword, status, page })) - watch 它,并配
{ deep: true } - 回调中可直接比较
newVal.keyword !== oldVal.keyword,逻辑清晰、不易漏判 - 首次触发仍需判空:
if (oldVal) { /* 安全解构 */ }
数组或对象浅层变更:注意“值变 ≠ 引用变”
arr.push()、obj.name = 'x' 这类操作不改变引用,但内容已变。watch 默认检测不到。
- 监听数组建议用
computed(() => [...arr])或监听其长度() => arr.length - 监听对象某字段,优先写
watch(() => obj.field, ...)而非整个obj - 若必须监听整个对象且含浅层修改,
deep: true是必要选择


















