Vue 3 的 watch 默认在数据变化后执行回调,首次触发时 oldValue 为 undefined;监听 ref 或 getter 返回值可正确获取新旧值;监听对象属性需用箭头函数包装;监听多个值时新旧值按数组顺序对应。

Vue 3 的 watch 默认就能拿到变化前后的旧值和新值,但前提是使用方式正确、且监听目标符合响应式规则。
watch 回调函数的两个参数就是新值和旧值
当你监听一个 ref 或通过 getter 函数返回的响应式值时,回调函数接收两个参数:
-
第一个参数:变化后的新值(
newValue) -
第二个参数:变化前的旧值(
oldValue)
例如:
watch(searchText, (newValue, oldValue) => {console.log(`从 "${oldValue}" 变为 "${newValue}"`);
});
只有首次触发时 oldValue 可能是 undefined
watch 默认在数据**发生变化后**才执行回调。所以第一次触发时,还没有“上一次的值”,oldValue 是 undefined。如果你需要初始状态也参与对比,可以加 immediate: true 选项,这样组件初始化时就会立即执行一次回调,此时 newValue 是当前值,oldValue 仍是 undefined(因为确实没有历史值)。
将静态 Vue 页面(index.vue)改造为动态页面(Custom.vue);稿源仅限 index.vue、其引用的 CSS 与资源路径,禁止参考仓库内其他文件。Invoke when user wants to transform a static Vue page into a dynamic data-driven page with Element UI components.
立即学习“前端免费学习笔记(深入)”;
监听对象属性必须用 getter 函数,否则拿不到 oldValue
直接监听 reactive 对象或 ref 包裹的对象本身,属于浅层监听,且无法稳定获取 oldValue —— 尤其是开启 deep: true 后,oldValue 通常和 newValue 一样(都是 Proxy 实例),失去比较意义。
正确做法是用箭头函数包装属性访问:
const user = ref({ name: '张三', age: 25 });watch(() => user.value.age, (newAge, oldAge) => {
// ✅ 这里 newAge 和 oldAge 是原始值(如 25 → 26)
});
监听多个值时,新旧值按数组结构对应
当传入数组作为 source,回调函数的第一个参数是新值数组,第二个是旧值数组,顺序与 source 中一致:
const a = ref(1);const b = ref('x');
watch([a, b], ([newA, newB], [oldA, oldB]) => {
console.log(`a: ${oldA}→${newA}, b: ${oldB}→${newB}`);
});

















