现在我转变一下思路,用实例来看源码。
首先用new vue生成实例,生成大概是这个样子
即使源码开始处的factory函数,此函数最后 return Vue;那我们来看看vue初始化是什么,找到Vue定义是在4710行,是一个函数,并申明是一个构造函数,必须用new 去生成实例。
其中函数中的options,即使 vue()中的对象,包括el,data等。继续追this._init()函数,最后发现在4575行的initMixin函数,且在4722行执行,函数内主要在Vue的原型链上添加了_init函数,
`
function initMixin (Vue) {
// 将_init函数添加到vue的原型链上
Vue.prototype._init = function (options) {
var vm = this;
//设置_uid唯一标识,uid3++;
var startTag, endTag;
/* 主要是使用perfomance来实现组件性能监控,获取组件等在浏览器上的性能参数,在1868-1885行主要定义了mark,message两个方法,监听起始和结束标签的加载时间*/
if ("development" !== 'production' && config.performance && mark) {
startTag = "vue-perf-start:" + (vm._uid);
endTag = "vue-perf-end:" + (vm._uid);
mark(startTag);
}
// 设置_isVue为true,标记这是一个Vue的实例
vm._isVue = true;
// 区分是new生成的实例或者是Vue.component,Vue.direactrive生成的组件或者指令,
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 {
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
);
}
/* istanbul ignore else */
{
// 这个函数在1949行,如果支持proxy并且传入的options里面有render,用proxy调用render方法
initProxy(vm);
}
// 暴露自己
vm._self = vm;
initLifecycle(vm);
initEvents(vm);
initRender(vm);
callHook(vm, 'beforeCreate');
initInjections(vm); // resolve injections before data/props
initState(vm);
initProvide(vm); // resolve provide after data/props
callHook(vm, 'created');
/* istanbul ignore if */
if ("development" !== 'production' && config.performance && mark) {
vm._name = formatComponentName(vm, false);
mark(endTag);
measure(("vue " + (vm._name) + " init"), startTag, endTag);
}
if (vm.$options.el) {
vm.$mount(vm.$options.el);
}
};
}
`