vue watch 实现原理
Vue 中 watch 的实现原理
Vue 的 watch 功能用于监听数据变化并执行回调函数,其核心原理基于响应式系统和依赖收集机制。
响应式系统基础
Vue 通过 Object.defineProperty 或 Proxy(Vue 3)实现数据劫持。当数据被访问时,依赖会被收集到当前执行的 Watcher 中;当数据变更时,触发依赖通知所有关联的 Watcher 执行更新。

Watcher 类的角色
watch 选项或 $watch 方法会创建一个 Watcher 实例。Watcher 的核心功能包括:

- 记录回调函数和监听的表达式(如
data的属性路径)。 - 通过
getter主动求值,触发依赖收集。 - 在数据变化时调用回调函数。
// 简化版 Watcher 示例
class Watcher {
constructor(vm, expOrFn, callback) {
this.vm = vm;
this.getter = parsePath(expOrFn); // 解析属性路径(如 'a.b.c')
this.callback = callback;
this.value = this.get(); // 初始求值,触发依赖收集
}
get() {
Dep.target = this; // 标记当前 Watcher
const value = this.getter.call(this.vm, this.vm); // 求值,触发数据劫持的 getter
Dep.target = null; // 收集完成后清除标记
return value;
}
update() {
const oldValue = this.value;
this.value = this.get(); // 重新求值
this.callback.call(this.vm, this.value, oldValue); // 执行回调
}
}
依赖收集与触发流程
- 依赖收集:初始化 Watcher 时调用
get(),访问监听的数据属性,触发属性的getter,将当前 Watcher 添加到属性的依赖列表(Dep 中)。 - 触发更新:当数据被修改时,触发
setter,通知 Dep 中所有 Watcher 执行update(),最终调用回调函数。
深度监听的实现
当设置 deep: true 时,Watcher 会递归遍历监听对象的所有子属性,强制触发它们的 getter,从而收集深层依赖:
if (this.deep) {
traverse(value); // 递归遍历对象/数组
}
异步更新队列
默认情况下,Vue 会将 Watcher 的更新推入异步队列(nextTick 机制),避免重复计算和频繁 DOM 操作。可通过 sync: true 强制同步执行。
与计算属性的区别
- 计算属性:基于依赖缓存,只有依赖变化时才重新计算,适用于派生数据。
- 侦听器:无缓存,每次变化都执行回调,适合异步或开销较大的操作。






