vue原理分析(十四)研究new Vue()中的 initProvide
在Vue.prototype._init 中有一些init函数,今天我们来研究这些init函数
Vue.prototype._init = function (options) {
......
{
initProxy(vm);
}
......
initLifecycle(vm);
initEvents(vm);
initRender(vm);
callHook$1(vm, 'beforeCreate', undefined, false /* setContext */);
initInjections(vm); // resolve injections before data/props
initState(vm);
initProvide(vm); // resolve provide after data/props
callHook$1(vm, 'created');
......
}
上一篇中已经研究了 initState ,今天我们往下研究
initProvide(vm);
function initProvide(vm) {
const provideOption = vm.$options.provide;
if (provideOption) {
// 获取provided的对象
const provided = isFunction(provideOption)
? provideOption.call(vm)
: provideOption;
// 如过不是object对象且为null直接返回
if (!isObject(provided)) {
return;
}
// 解析provide
const source = resolveProvided(vm);
// IE9 doesn't support Object.getOwnPropertyDescriptors so we have to
// iterate the keys ourselves.
// IE9不支持Object.getOwnPropertyDescriptors所以这里必须自己去迭代keys
const keys = hasSymbol ? Reflect.ownKeys(provided) : Object.keys(provided);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
Object.defineProperty(source, key, Object.getOwnPropertyDescriptor(provided, key));
}
}
}
function resolveProvided(vm) {
// by default an instance inherits its parent's provides object
// but when it needs to provide values of its own, it creates its
// own provides object using parent provides object as prototype.
// this way in `inject` we can simply look up injections from direct
// parent and let the prototype chain do the work.
// 默认情况下,实例继承其父级的provides对象,
// 但当它需要提供自己的值时,
// 它会使用父级provides对象作为原型创建自己的provide对象。
// 通过这种方式,在“inject”中,我们可以简单地从直接父级查找注入,并让原型链来完成工作。
// existing 是 实例上的 _provided
const existing = vm._provided;
const parentProvides = vm.$parent && vm.$parent._provided;
// 如果父级上的_provided和实例上的_provided一致,就将父级上的parentProvides赋给实例上的_provided
// 否则直接返回实例上的属性
if (parentProvides === existing) {
return (vm._provided = Object.create(parentProvides));
}
else {
return existing;
}
}