vue watch怎么实现的
Vue 的 watch 实现原理
Vue 的 watch 功能通过响应式系统的依赖收集和触发机制实现。其核心是监听数据变化并执行回调函数。
初始化阶段
在 Vue 实例初始化时,如果选项中有 watch 配置,会调用 initWatch 方法。该方法遍历 watch 选项,为每个监听属性创建对应的 Watcher 实例。
function initWatch(vm, watch) {
for (const key in watch) {
const handler = watch[key];
createWatcher(vm, key, handler);
}
}
创建 Watcher
createWatcher 方法会根据监听属性的配置(函数、对象、字符串)创建对应的 Watcher 实例。如果是深度监听(deep: true),会递归遍历对象的所有属性进行依赖收集。
function createWatcher(vm, expOrFn, handler, options) {
if (isPlainObject(handler)) {
options = handler;
handler = handler.handler;
}
if (typeof handler === 'string') {
handler = vm[handler];
}
return vm.$watch(expOrFn, handler, options);
}
依赖收集
当 Watcher 实例化时,会执行 get 方法触发监听属性的 getter。在 getter 中,当前 Watcher 会被添加到依赖列表中(Dep.target)。
class Watcher {
constructor(vm, expOrFn, cb, options) {
this.vm = vm;
this.cb = cb;
this.deep = !!options.deep;
this.getter = parsePath(expOrFn);
this.value = this.get();
}
get() {
pushTarget(this);
const value = this.getter.call(this.vm, this.vm);
if (this.deep) traverse(value);
popTarget();
return value;
}
}
触发更新
当监听的数据发生变化时,会触发 setter 通知所有依赖的 Watcher 执行 update 方法。最终调用回调函数并传入新旧值。
class Watcher {
update() {
const oldValue = this.value;
this.value = this.get();
this.cb.call(this.vm, this.value, oldValue);
}
}
深度监听实现
深度监听通过递归遍历对象的所有属性,触发每个属性的 getter 进行依赖收集。
function traverse(val) {
if (typeof val !== 'object') return;
for (const key in val) {
traverse(val[key]);
}
}
立即执行
如果配置了 immediate: true,会在 Watcher 创建后立即执行回调函数。
if (options.immediate) {
cb.call(vm, watcher.value);
}
注销监听
调用 $watch 返回的函数可以注销监听,内部通过 Watcher 的 teardown 方法实现。
Vue.prototype.$watch = function(expOrFn, cb, options) {
const watcher = new Watcher(this, expOrFn, cb, options);
return function unwatchFn() {
watcher.teardown();
};
};
通过以上机制,Vue 实现了高效的数据监听功能,能够精确响应数据变化并执行相应的回调逻辑。







