vue watch实现过程
Vue 中 watch 的实现过程
Vue 的 watch 功能通过响应式系统的依赖收集和触发机制实现。以下是其核心实现逻辑:
初始化 watch
在组件初始化阶段,Vue 会遍历 watch 选项,为每个监听属性创建对应的 Watcher 实例。这个 Watcher 会被标记为用户 watch(user: true),区别于渲染 Watcher。

// 简化后的初始化逻辑
function initWatch(vm, watch) {
for (const key in watch) {
const handler = watch[key];
createWatcher(vm, key, handler);
}
}
创建 Watcher
Watcher 会解析监听的目标路径(如 a.b.c),并通过 getter 函数建立依赖关系。当被监听的值变化时,触发回调:
// 简化后的 Watcher 创建
new Watcher(vm, getter, callback, { user: true });
依赖收集过程
- 首次求值:
Watcher会主动执行getter函数,访问被监听的数据,触发属性的get拦截器。 - 依赖记录:在
get拦截器中,当前Watcher会被添加到属性的依赖列表(dep.subs)中。
触发更新
当被监听的数据被修改时:

- 属性的
set拦截器会通知所有依赖的Watcher。 Watcher执行回调函数,传入新值和旧值。- 如果设置了
immediate: true,回调会在创建Watcher时立即执行一次。
深层监听实现
对于 deep: true 的监听:
Watcher会递归遍历对象的所有属性。- 对每个子属性都触发
get拦截器,强制收集依赖。
// 简化后的 deep 处理
function traverse(val) {
if (isObject(val)) {
for (const key in val) {
traverse(val[key]);
}
}
}
异步队列处理
Vue 通过异步队列(nextTick)批量处理 watch 回调,确保:
- 多次同步修改只会触发一次回调。
- 回调执行时 DOM 已更新完毕(与渲染
Watcher的执行顺序相关)。
与计算属性的区别
watch是主动监听,适合执行副作用(如异步操作)。- 计算属性是基于缓存的被动计算,适合派生数据。
性能优化建议
- 避免过度使用
deep,尤其是监听大型对象。 - 对于需要监听多个属性的场景,考虑使用
computed计算后再监听。 - 必要时使用
unwatch手动解除监听。






