官方原理图

参考如下所示:
调试分析

数据改变 驱动试图改变的调用栈如右图所示
changeMsg
this.msg === '111'的变化 触发了proxySetter(val)
代理到了this._data.msg = '111'
触发了reactiveSetter
-触发setter的dep.notify
派发更新 触发了queueWatch ->nextTick -> flushCallbacks flushSchedulerQueue
触发了watcher.run
触发了渲染watcher的get求值 this.getter.call 就是 渲染watcher的 getter updateComponent
当成getter传入到渲染watcher中去的
// vm._render() 返回对应的VNode 经过patch patchNode diff 等 patch就是把vnode 映射成 dom 通过insert 插入到父节点中去
updateComponent = function () {
vm._update(vm._render(), hydrating);
};
// 2次代理 代理到vm上去的
function proxy (target, sourceKey, key) {
sharedPropertyDefinition.get = function proxyGetter () {
return this[sourceKey][key]
};
sharedPropertyDefinition.set = function proxySetter (val) {
this[sourceKey][key] = val;
};
Object.defineProperty(target, key, sharedPropertyDefinition);
}
Watcher.prototype.run = function run () {
if (this.active) {
var value = this.get();
if (
value !== this.value ||
// Deep watchers and watchers on Object/Arrays should fire even
// when the value is the same, because the value may
// have mutated.
isObject(value) ||
this.deep
) {
// set new value
var oldValue = this.value;
this.value = value;
if (this.user) {
try {
this.cb.call(this.vm, value, oldValue);
} catch (e) {
handleError(e, this.vm, ("callback for watcher \"" + (this.expression) + "\""));
}
} else {
this.cb.call(this.vm, value, oldValue);
}
}
}
};
/**
* Evaluate the getter, and re-collect dependencies.
*/
Watcher.prototype.get = function get () {
pushTarget(this);
var value;
// 当前vue的实例 vueComponent this.getter new渲染Watcher的定义了 updateComponent
var vm = this.vm;
try {
value = this.getter.call(vm, vm);
} catch (e) {
if (this.user) {
handleError(e, vm, ("getter for watcher \"" + (this.expression) + "\""));
} else {
throw e
}
} finally {
// "touch" every property so they are all tracked as
// dependencies for deep watching
if (this.deep) {
traverse(value);
}
popTarget();
this.cleanupDeps();
}
return value
};

// mountComponent
function mountComponent (
vm,
el,
hydrating
) {
vm.$el = el;
if (!vm.$options.render) {
vm.$options.render = createEmptyVNode;
}
callHook(vm, 'beforeMount');
var updateComponent;
updateComponent = function () {
vm._update(vm._render(), hydrating);
};
// we set this to vm._watcher inside the watcher's constructor
// since the watcher's initial patch may call $forceUpdate (e.g. inside child
// component's mounted hook), which relies on vm._watcher being already defined
new Watcher(vm, updateComponent, noop, null, true /* isRenderWatcher */);
hydrating = false;
// manually mounted instance, call mounted on self
// mounted is called for render-created child components in its inserted hook
if (vm.$vnode == null) {
vm._isMounted = true;
callHook(vm, 'mounted');
}
return vm
}
网友评论