1.vue使用了5个函数来对vue进行扩展
1. initMixin
vm._uid = uid++
首先给vue实例设置了唯一标识符uid,每次实例化都会递增
// a flag to avoid this being observed
vm._isVue = true
给vm对象设置标志,避免被监听
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
)
}
合并options,如果是组件则进入第一个分支,页面进入第二个分支,这里调用mergeOptions方法实现options的合并,该方法有三个参数,第一个是resolveConstructorOptions方法返回值(vm.constructor的options),第二是new Vue时传入的值(自定义的options),第三个是vue对象本身。mergeOptions就是通过一系列的合并策略,将Vue的构造函数以及自定义的options进行合并。
1.1 mergeOptions(位于core/util/options.js)
export function mergeOptions(
parent: Object,
child: Object,
vm?: Component
): Object {
if (process.env.NODE_ENV !== "production") {
// 1.校验组件名称的合法性
checkComponents(child);
}
//2.如果传入的是类型是function,则取其options
if (typeof child === "function") {
child = child.options;
}
//3.格式化props,inject,directives
/*
props:[],
props:{
info:String,
default:''
}
*/
normalizeProps(child, vm);
normalizeInject(child, vm);
normalizeDirectives(child);
// 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.
//在子选项上应用扩展和混合,
//空对象的时候不调用
//这是另一个合并选项调用的结果。
//只合并具有_base属性的选项
if (!child._base) {
if (child.extends) {
parent = mergeOptions(parent, child.extends, vm);
}
if (child.mixins) {
for (let i = 0, l = child.mixins.length; i < l; i++) {
parent = mergeOptions(parent, child.mixins[i], vm);
}
}
}
const options = {};
let key;
for (key in parent) {
mergeField(key);
}
for (key in child) {
if (!hasOwn(parent, key)) {
mergeField(key);
}
}
function mergeField(key) {
const strat = strats[key] || defaultStrat;
options[key] = strat(parent[key], child[key], vm, key);
}
return options;
}
该方法有三个入参,parent为resolveConstructorOptions返回的值(Vue的构造函数的options),child是我们new Vue时传入的数组对象(自定义的options),vm是Vue对象本身。方便起见,下面我们就用parent和child来称呼这两种options。
(1)合法性校验
if (process.env.NODE_ENV !== "production") {
// 1.校验组件名称的合法性
checkComponents(child);
}
规范组件的命名
(2)如果传入的是类型是function,则取其options
//2.如果传入的是类型是function,则取其options
if (typeof child === "function") {
child = child.options;
}
(3)校验props,Inject,directives的值
normalizeProps(child, vm);
normalizeInject(child, vm);
normalizeDirectives(child);
(4)extends与minxins处理
//在子选项上应用扩展和混合,
//空对象的时候不调用
//这是另一个合并选项调用的结果。
//只合并具有_base属性的选项
if (!child._base) {
if (child.extends) {
parent = mergeOptions(parent, child.extends, vm);
}
if (child.mixins) {
for (let i = 0, l = child.mixins.length; i < l; i++) {
parent = mergeOptions(parent, child.mixins[i], vm);
}
}
}
判断是否有extends与minxins属性,使用mergeOptions进行递归调用
(5)合并策略
const options = {};
let key;
for (key in parent) {
mergeField(key);
}
for (key in child) {
if (!hasOwn(parent, key)) {
mergeField(key);
}
}
function mergeField(key) {
const strat = strats[key] || defaultStrat;
options[key] = strat(parent[key], child[key], vm, key);
}
对每种属性(key)有不同的合并策略strat[key],我们以钩子函数的合并为例。定义钩子函数的合并策略的处理方法为mergeHook
export const LIFECYCLE_HOOKS = [
'beforeCreate',
'created',
'beforeMount',
'mounted',
'beforeUpdate',
'updated',
'beforeDestroy',
'destroyed',
'activated',
'deactivated',
'errorCaptured',
'serverPrefetch'
]
function mergeHook(
parentVal: ?Array<Function>,
childVal: ?Function | ?Array<Function>
): ?Array<Function> {
const res = childVal
? parentVal
? parentVal.concat(childVal)
: Array.isArray(childVal)
? childVal
: [childVal]
: parentVal;
return res ? dedupeHooks(res) : res;
}
1.2 resolveConstructorOptions
export function resolveConstructorOptions (Ctor: Class<Component>) {
let options = Ctor.options
if (Ctor.super) {
const superOptions = resolveConstructorOptions(Ctor.super)
const cachedSuperOptions = Ctor.superOptions
if (superOptions !== cachedSuperOptions) {
// super option changed,
// need to resolve new options.
Ctor.superOptions = superOptions
// check if there are any late-modified/attached options (#4976)
const modifiedOptions = resolveModifiedOptions(Ctor)
// update base extend options
if (modifiedOptions) {
extend(Ctor.extendOptions, modifiedOptions)
}
options = Ctor.options = mergeOptions(superOptions, Ctor.extendOptions)
if (options.name) {
options.components[options.name] = Ctor
}
}
}
return options
}
该方法的接受的参数是vm.constructor,即构造函数Vue,返回构造函数的options