在new vue(options)的过程中对于数据做了十分复杂的处理,例如处理inject和provide,调用恰当的钩子函数,注册响应式,初始化watcher,初始化计算属性,初始化事件中心等等,本章将会详细讲解注册响应式之外的内容,响应式内容很多且难以消化,单出来进行细致分析。
- initProxy()
- initLifecycle()
- initEvents()
- initRender()
- initInjections()
- initState() //下一章分析
- initProvide()
- callHook()
initProxy
通过初始化代理(开发环境下)给使用者部分提示。代码如下:
if (process.env.NODE_ENV !== 'production') {
initProxy(vm);
} else {
vm._renderProxy = vm;
}
// function initProxy
initProxy = function initProxy(vm) {
if (hasProxy) {
// ... handlers中包含一些陷阱
vm._renderProxy = new Proxy(vm, handlers);
} else {
vm._renderProxy = vm;
}
};
在开发环境下,vue使用代理对vm部分访问方式进行一次拦截(设置代理陷阱),vue为了在开发环境下进行安全检查并对使用者进行提示,分别设置了get和has陷阱,生产环境下renderProxy就是vm本身,也就没有各种提示了。
initLifecycle
初始化当前vm的部分重要标识属性和构造vm引用链。如下代码:
function initLifecycle(vm) {
var options = vm.$options;
var parent = options.parent;
if (parent && !options.abstract) {
while (parent.$options.abstract && parent.$parent) {
parent = parent.$parent;
}
parent.$children.push(vm);
}
vm.$parent = parent;
options.parents是创建子组件vm时,父组件将自身的vm传递进来。但是需要特别注意的是,首先判断当前options的抽象标志abstract是不是true,如果是true就代表当前vm不需要添加到整个组件树上,也就说明当前组件是个抽象组件。就类似keep-alive实际上就是一个抽象组件。
如果当前组件没有配置abstract:true,就需要添加到vm树形关系上去,这时候就需要确定其父级,当然,其父级也不能为抽象的,所以就通过parent = parent.$parent
的方式不断向上层寻找,找到第一个非抽象节点作为当前vm的父级vm,同时也将当前vm添加到这个父级的$children数组中去,也就是***双向持有引用***。
vm.$root = parent ? parent.$root : vm;
vm.$children = [];
vm.$refs = {
};
vm._watcher = null;
vm._inactive = null;
vm._directInactive = false;
vm._isMounted = false;
vm._isDestroyed = false;
vm._isBeingDestroyed = false;
}
接下来拿到$root,指向最根部的vm,随即创建子vm容器children,创建refs容器。创建_watcher,将保存当前vm的渲染wa