vue watch 实现 原理
Vue watch 的实现原理
Vue 的 watch 机制基于响应式系统,通过依赖收集和派发更新实现数据变化的监听。以下是其核心实现原理:
依赖收集与响应式系统
Vue 的响应式系统通过 Object.defineProperty 或 Proxy(Vue 3)劫持数据对象的属性访问和修改。当在组件中定义 watch 时,Vue 会将 watcher 实例添加到当前属性的依赖列表中。
- Getter 触发依赖收集:首次访问被监听的数据时,触发 getter,将当前 watcher 添加到依赖列表。
- Setter 触发更新:数据变化时触发 setter,通知所有依赖的 watcher 执行回调。
Watcher 类
Vue 内部通过 Watcher 类实现监听逻辑:
- 初始化阶段:在组件初始化时,遍历
watch选项,为每个监听属性创建对应的Watcher实例。 - 回调执行:当数据变化时,watcher 会执行用户定义的回调函数,并传入新旧值。
深度监听实现
当设置 deep: true 时,Vue 会递归遍历对象的所有属性,为每个子属性绑定监听:
traverse(value) {
if (isObject(value)) {
Object.keys(value).forEach(key => {
traverse(value[key])
})
}
}
立即执行与回调调度
若设置 immediate: true,Vue 会在 watcher 创建后立即执行一次回调。通过 scheduler 控制回调的执行时机,例如在 nextTick 中批量处理更新。
Vue 3 的优化
Vue 3 使用 Proxy 替代 Object.defineProperty,并引入 effect 和 ReactiveEffect 类重构响应式系统。watch API 通过 effect 自动跟踪依赖,性能更高。
示例代码
以下是简化的 watcher 实现逻辑:

class Watcher {
constructor(vm, expOrFn, cb, options) {
this.vm = vm
this.cb = cb
this.deep = !!options.deep
if (typeof expOrFn === 'function') {
this.getter = expOrFn
} else {
this.getter = parsePath(expOrFn)
}
this.value = this.get()
}
get() {
pushTarget(this) // 将当前 watcher 设置为全局活动 watcher
const value = this.getter.call(this.vm, this.vm)
if (this.deep) traverse(value) // 深度监听
popTarget() // 恢复之前的 watcher
return value
}
update() {
const oldValue = this.value
this.value = this.get()
this.cb.call(this.vm, this.value, oldValue)
}
}
关键点总结
- 基于响应式系统的 getter/setter 或 Proxy 实现数据监听。
- 每个
watch对应一个Watcher实例,通过依赖收集关联数据与回调。 - 深度监听通过递归遍历对象属性实现。
- Vue 3 的
watch利用 Composition API 的effect机制,实现更细粒度的依赖跟踪。






