vue watch实现原理
Vue watch 的实现原理
Vue 的 watch 功能基于响应式系统和依赖收集机制实现,核心是通过监听数据变化并触发回调函数。
依赖收集与响应式系统
Vue 通过 Object.defineProperty 或 Proxy 拦截数据的读写操作。在初始化 watch 时,会执行一次回调函数或读取被监听的值,触发属性的 getter,从而将当前 watcher 实例添加到依赖列表中。
// 简化版依赖收集逻辑
function defineReactive(obj, key) {
let value = obj[key]
const dep = new Dep() // 依赖管理器
Object.defineProperty(obj, key, {
get() {
if (Dep.target) { // 当前正在计算的watcher
dep.addSub(Dep.target)
}
return value
},
set(newVal) {
if (newVal === value) return
value = newVal
dep.notify() // 通知所有订阅者更新
}
})
}
Watcher 类的作用
每个 watch 会创建一个 Watcher 实例,负责执行回调函数。当依赖的数据变化时,Watcher 会被通知并重新求值。
class Watcher {
constructor(vm, expOrFn, callback) {
this.vm = vm
this.getter = parsePath(expOrFn) // 解析属性路径
this.callback = callback
this.value = this.get() // 首次收集依赖
}
get() {
Dep.target = this // 标记当前watcher
const value = this.getter.call(this.vm, this.vm)
Dep.target = null // 收集完成后清除标记
return value
}
update() {
const oldValue = this.value
this.value = this.get()
this.callback.call(this.vm, this.value, oldValue)
}
}
深层监听与立即触发
- 深层监听(deep):递归遍历对象的所有属性,强制触发它们的
getter以收集依赖。 - 立即触发(immediate):在
Watcher创建时直接调用一次回调函数。
if (this.deep) {
traverse(value) // 递归遍历对象
}
if (this.immediate) {
callback.call(vm, value, null)
}
异步更新队列
Vue 会将触发的 watcher 推入队列,在下一个事件循环中统一执行,避免重复计算和频繁更新。

function queueWatcher(watcher) {
nextTick(flushSchedulerQueue)
}
总结
Vue 的 watch 通过响应式系统追踪依赖,在数据变化时通过 Watcher 机制调度回调。其核心在于依赖收集、派发更新和异步批量处理,实现了高效的数据监听。






