Vue 构造函数
function Vue (options) {
if (!(this instanceof Vue)
) {
warn('Vue is a constructor and should be called with the `new` keyword');
}
this._init(options);
}
Vue.prototype._init 初始化函数
vm._uid = uid$3++; (给每个实例分配一个自增id)
给当前实例标记,源码注释: a flag to avoid this being observed
vm._isVue = true; 也可以使用
_isVue来阻止vm的observer;
合并参数
判断当前实例是否为组件
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 {
处理options参数,合并参数
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
);
}
initInternalComponent方法处理组件
function initInternalComponent (vm, options) {
var opts = vm.$options = Object.create(vm.constructor.options);
// doing this because it's faster than dynamic enumeration.
var parentVnode = options._parentVnode;
opts.parent = options.parent;
opts._parentVnode = parentVnode;
var vnodeComponentOptions = parentVnode.componentOptions;
opts.propsData = vnodeComponentOptions.propsData;
opts._parentListeners = vnodeComponentOptions.listeners;
opts._renderChildren = vnodeComponentOptions.children;
opts._componentTag = vnodeComponentOptions.tag;
if (options.render) {
opts.render = options.render;
opts.staticRenderFns = options.staticRenderFns;
}
}
在内置组件的options上加上一些属性
resolveConstructorOptions方法返回options参数
参数Ctor是Vue构造函数(vm.constructor)
function resolveConstructorOptions (Ctor) {
var options = Ctor.options;
如果是new Vue调用,options就是源码中的 initGlobalAPI 方法会在初始化脚本时候给Vue构造函数增加options属性。
如果是Vue.extend调用,options就是 Vue.extend 方法中给VueComponent构造函数增加的options属性。
if (Ctor.super) { //判断是否为Vue.extend创建的一个“子类” Vue.extend方法中会加上super属性
var superOptions = resolveConstructorOptions(Ctor.super);
此时的Ctor是VueComponent构造函数,
Ctor.super为Vue构造函数 ( Vue.extend 中定义),所以这个返回值是 initGlobalAPI 方法会在初始化脚本时候给Vue构造函数增加options属性。
var cachedSuperOptions = Ctor.superOptions;
返回值是Vue.extend中定义的superOptions
if (superOptions !== cachedSuperOptions) {
检查Vue的options是否发生变化
superOptions有新变化则缓存superOptions 列如Vue.mixin()
// super option changed,
// need to resolve new options.
Ctor.superOptions = superOptions;
// check if there are any late-modified/attached options (#4976)
检查"自身"的options是否发生变化
var modifiedOptions = resolveModifiedOptions(Ctor);
// update base extend options
更新修改的options
if (modifiedOptions) {
extend(Ctor.extendOptions, modifiedOptions);
}
合并参数
options = Ctor.options = mergeOptions(superOptions, Ctor.extendOptions);
if (options.name) {
options.components[options.name] = Ctor;
}
}
}
return options
}
resolveModifiedOptions 方法返回update的属性
function resolveModifiedOptions (Ctor) {
var modified;
var latest = Ctor.options; 最新的options
var sealed = Ctor.sealedOptions; 这个值为 Vue.extend() 中定义
for (var key in latest) {
if (latest[key] !== sealed[key]) { 判断两个options的key是否相等
if (!modified) { modified = {}; }
modified[key] = latest[key]; 取最新的值
}
}
return modified
}
mergeOptions 合并策略
/**
* Merge two option objects into a new one.
* Core utility used in both instantiation and inheritance.
*/
function mergeOptions (
parent,
child,
vm
) {
{
checkComponents(child);
检测组件的命名规范
}
if (typeof child === 'function') {
child = child.options;
}
normalizeProps(child, vm); 规范化,Props 转为对象
normalizeInject(child, vm); 规范化,Inject 转为对象
normalizeDirectives(child); 规范化,Inject 转为对象
// Apply extends and mixins on the child options,
// but only if it is a raw options object that isn't
// the result of another mergeOptions call.
// Only merged options has the _base property.
不是根组件的话 调用自身合并option参数
if (!child._base) {
if (child.extends) {
parent = mergeOptions(parent, child.extends, vm);
}
if (child.mixins) {
for (var i = 0, l = child.mixins.length; i < l; i++) {
parent = mergeOptions(parent, child.mixins[i], vm);
}
}
}
var options = {};
var key;
for (key in parent) {
mergeField(key);
}
for (key in child) {
if (!hasOwn(parent, key)) {
mergeField(key);
}
}
strats为合并策略,分别用不用的方法合并options参数 (data, created, methods 等等)
function mergeField (key) {
var strat = strats[key] || defaultStrat;
options[key] = strat(parent[key], child[key], vm, key);
}
return options
}
initProxy
function initProxy (vm) {
if (hasProxy) {
// determine which proxy handler to use
var options = vm.$options;
var handlers = options.render && options.render._withStripped
? getHandler
: hasHandler;
vm._renderProxy = new Proxy(vm, handlers);
} else {
vm._renderProxy = vm;
}
};
这个方法主要给vm增加一个_renderProxy属性,并且代理到vm上,之后_render()的时候会用到
initLifecycle(vm);
initEvents(vm);
initRender(vm);
这三个方法主要是是初始化一些_watcher,_isMounted等属性,以及listeners事件,$createElement方法
在new Vue() 到beforeCreate之间主要是用mergeOptions方法合并optoins参数,如用到了mixins,extends等,并且初始化一些属性