vue watch实现过程
Vue 的 watch 实现原理
Vue 的 watch 功能基于响应式系统,通过依赖收集和触发回调实现数据监听。以下是核心实现过程:
依赖收集阶段
在组件初始化时,watch 选项会被解析并注册为响应式数据的依赖。Vue 遍历 watch 配置的每个属性,为每个监听目标创建一个 Watcher 实例。这个 Watcher 会记录回调函数和可选的配置(如 deep、immediate)。
当首次访问被监听的属性时,触发 getter 方法,将当前 Watcher 添加到依赖列表(Dep 的 subs 数组)中,建立数据与观察者的关联。
回调触发阶段
当被监听的数据发生变化时,触发 setter 方法,通知所有订阅该数据的 Watcher 实例执行更新。Watcher 会调用注册的回调函数,传入新值和旧值。如果设置了 deep: true,Vue 会递归遍历对象的所有属性以收集深层依赖。
异步更新队列
默认情况下,watch 的回调会被推入异步更新队列(通过 nextTick 实现),确保多次数据变更合并为一次回调执行。设置 sync: true 可强制同步执行。

代码示例
// 简单实现核心逻辑
class Dep {
constructor() {
this.subs = []
}
addSub(watcher) {
this.subs.push(watcher)
}
notify() {
this.subs.forEach(watcher => watcher.update())
}
}
class Watcher {
constructor(vm, exp, cb, options) {
this.vm = vm
this.getter = parsePath(exp)
this.cb = cb
this.value = this.get()
if (options.immediate) {
this.cb.call(vm, this.value)
}
}
get() {
Dep.target = this
const value = this.getter.call(this.vm, this.vm)
Dep.target = null
return value
}
update() {
const oldValue = this.value
this.value = this.get()
this.cb.call(this.vm, this.value, oldValue)
}
}
function defineReactive(obj, key) {
const dep = new Dep()
let val = obj[key]
Object.defineProperty(obj, key, {
get() {
if (Dep.target) dep.addSub(Dep.target)
return val
},
set(newVal) {
if (newVal === val) return
val = newVal
dep.notify()
}
})
}
使用方式对比
选项式 API
watch: {
'obj.property'(newVal, oldVal) {
// 处理变化
},
arr: {
handler: 'methodName',
deep: true
}
}
组合式 API
import { watch } from 'vue'
watch(
() => state.someProp,
(newVal, oldVal) => {
// 回调逻辑
},
{ immediate: true }
)
性能优化建议
对于复杂数据结构,避免不必要的深度监听。考虑使用计算属性预处理数据,减少回调触发频率。必要时使用 flush: 'post' 确保 DOM 更新后执行回调。






