1、Vue 的初始化过程(new Vue(options))都做了什么?
在main.js 加入如下代码
代码语言:javascript复制debugger
new Vue(
{
el: '#app',
router,
components: { App },
template: '<App/>'
})
Chrome浏览器调试
截屏2022-03-01 下午2.27.46.png
代码语言:javascript复制function Vue (options) {
if (process.env.NODE_ENV !== 'production' &&
!(this instanceof Vue)
) {
warn('Vue is a constructor and should be called with the `new` keyword');
}
this._init(options);
}
下一步
代码语言:javascript复制function initMixin (Vue) {
// 负责 Vue 的初始化过程
Vue.prototype._init = function (options) {
// vue 实例
var vm = this;
// a uid 每个 vue 实例都有一个 _uid,并且是依次递增的
vm._uid = uid$3 ;
var startTag, endTag;
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
startTag = "vue-perf-start:" (vm._uid);
endTag = "vue-perf-end:" (vm._uid);
mark(startTag);
}
// a flag to avoid this being observed
vm._isVue = true;
// merge options
if (options && options._isComponent) {
// optimize internal component instantiation
// since dynamic options merging is pretty slow, and none of the
// internal component options needs special treatment.
// 优化内部组件实例化,因为动态选项合并很慢,而且没有
// 内部组件选项需要特殊处理。
initInternalComponent(vm, options);
} else {
/**
* 初始化根组件时走这里,合并 Vue 的全局配置到根组件的局部配置,比如 Vue.component 注册的全局组件会合并到 根实例的 components 选项中
* 至于每个子组件的选项合并则发生在两个地方:
* 1、Vue.component 方法注册的全局组件在注册时做了选项合并
* 2、{ components: { xx } } 方式注册的局部组件在执行编译器生成的 render 函数时做了选项合并,包括根组件中的 components 配置
*/
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
);
}
/* istanbul ignore else */
if (process.env.NODE_ENV !== 'production') {
// 设置代理,将 vm 实例上的属性代理到 vm._renderProxy
initProxy(vm);
} else {
vm._renderProxy = vm;
}
// expose real self
vm._self = vm;
// 初始化组件实例关系属性,比如 $parent、$children、$root、$refs 等
initLifecycle(vm);
/**
* 初始化自定义事件,这里需要注意一点,所以我们在 <comp @click="handleClick" /> 上注册的事件,监听者不是父组件,
* 而是子组件本身,也就是说事件的派发和监听者都是子组件本身,和父组件无关
*/
initEvents(vm);
// 解析组件的插槽信息,得到 vm.$slot,处理渲染函数,得到 vm.$createElement 方法,即 h 函数
initRender(vm);
// 调用 beforeCreate 钩子函数
callHook(vm, 'beforeCreate');
// 初始化组件的 inject 配置项,得到 result[key] = val 形式的配置对象,然后对结果数据进行响应式处理,并代理每个 key 到 vm 实例
initInjections(vm); // resolve injections before data/props
// 数据响应式的重点,处理 props、methods、data、computed、watch
initState(vm);
/ /解析组件配置项上的 provide 对象,将其挂载到 vm._provided 属性上
initProvide(vm); // resolve provide after data/props
// 调用 created 钩子函数
callHook(vm, 'created');
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
vm._name = formatComponentName(vm, false);
mark(endTag);
measure(("vue " (vm._name) " init"), startTag, endTag);
}
// 如果发现配置项上有 el 选项,则自动调用 $mount 方法,也就是说有了 el 选项,就不需要再手动调用 $mount,反之,没有 el 则必须手动调用 $mount
if (vm.$options.el) {
vm.$mount(vm.$options.el);
}
};
}
● 处理组件配置项 ○ 初始化根组件时进行了选项合并操作,将全局配置合并到根组件的局部配置上 ○ 初始化每个子组件时做了一些性能优化,将组件配置对象上的一些深层次属性放到 vm.options 选项中,以提高代码的执行效率 ● 初始化组件实例的关系属性,比如 parent、children、root、refs 等 ● 处理自定义事件 ● 调用 beforeCreate 钩子函数 ● 初始化组件的 inject 配置项,得到 ret[key] = val 形式的配置对象,然后对该配置对象进行浅层的响应式处理(只处理了对象第一层数据),并代理每个 key 到 vm 实例上 ● 数据响应式,处理 props、methods、data、computed、watch 等选项 ● 解析组件配置项上的 provide 对象,将其挂载到 vm._provided 属性上 ● 调用 created 钩子函数 ● 如果发现配置项上有 el 选项,则自动调用 mount 方法,也就是说有了 el 选项,就不需要再手动调用 mount 方法,反之,没提供 el 选项则必须调用 mount ● 接下来则进入挂载阶段