vue原理分析(十二)研究new Vue()中的 initInjections
在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');
......
}
上一篇中已经研究了 initRender ,今天我们往下研究
initInjections(vm);
function initInjections(vm) {
const result = resolveInject(vm.$options.inject, vm);
if (result) {
toggleObserving(false);
Object.keys(result).forEach(key => {
/* istanbul ignore else */
{
defineReactive(vm, key, result[key], () => {
warn$2(`Avoid mutating an injected value directly since the changes will be ` +
`overwritten whenever the provided component re-renders. ` +
`injection being mutated: "${key}"`, vm);
});
}
});
toggleObserving(true);
}
}
我们逐步来解析代码
function initInjections(vm) {
const result = resolveInject(vm.$options.inject, vm);
......
}
这里是解析vm.$options.inject,返回解析后的对象
function resolveInject(inject, vm) {
if (inject) {
// inject is :any because flow is not smart enough to figure out cached
// inject 是 any 类型,因为flow不够智能,不能算出类型
// 创建一个空对象用于存放结果
const result = Object.create(null);
// 获取 key 名
// 如果支持hasSymbol ,则用 Reflect.ownKeys(inject) 否则用 Object.keys(inject)
const keys = hasSymbol ? Reflect.ownKeys(inject) : Object.keys(inject);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
// #6574 in case the inject object is observed...
// 如果是observed,则跳过
if (key === '__ob__')
continue;
const provideKey = inject[key].from;
if (provideKey in vm._provided) {
// 向父级_provided属性遍历查找属性值
// 因为父级组件使用provide选项注入数据时会将注入的数据存入自身实例的_provided属
result[key] = vm._provided[provideKey];
}
else if ('default' in inject[key]) {
// 当前的数据key存在默认值即default属性
const provideDefault = inject[key].default;
result[key] = isFunction(provideDefault)
? provideDefault.call(vm)
: provideDefault;
}
else {
warn$2(`Injection "${key}" not found`, vm);
}
}
return result;
}
}
function initInjections(vm) {
......
if (result) {
toggleObserving(false);
......
toggleObserving(true);
}
}
这两个toggleObserving是切换观察模式
function initInjections(vm) {
......
if (result) {
......
Object.keys(result).forEach(key => {
/* istanbul ignore else */
{
defineReactive(vm, key, result[key], () => {
warn$2(`Avoid mutating an injected value directly since the changes will be ` +
`overwritten whenever the provided component re-renders. ` +
`injection being mutated: "${key}"`, vm);
});
}
});
......
}
}
用foreach循环对keys中的每一个key做defineReactive处理