其实mixin的功能就是把传入的option和组件本身的option做merge
这样思考就超简单了,只需要调用mergeOptions就可以了。
mergeOptions(this.options, mixins)
这里说一下mergeOptions。mergeOptions是对传入的option进行合并的方法。
例如: 本来组件里调用了created
生命周期,mixin
里又传入了created
,那么定义的这两个created
放入一个队列里,在生命周期执行到created的时候,依次执行这个队列里的方法。
这里我们可以看一下callHook
这个函数
export function callHook (vm, hook) {
// 拿到对应的队列
const handlers = vm.$options[hook];
if (handlers) {
for (const handle of handlers) {
handle.call(vm);
}
}
}
因为目前实现的功能简单,只做生命周期的merge
首先遍历组件本身的option,再遍历mixins传入的对象
function mergeOptions (parent, child) {
const options = {};
for (const key in parent) {
mergeField(key);
}
for (const key in child) {
if (!hasOwnProperty.call(parent, key)) {
mergeField(key);
}
}
function mergeField (key) {
const strat = strats[key] || defaultStrat;
options[key] = strat(parent[key], child[key]);
}
return options;
}
function mergeHook (parentVal, childVal) {
return childVal
? parentVal
? parentVal.concat(childVal)
: Array.isArray(childVal)
? childVal
: [childVal]
: parentVal;
}
LIFECYCLE_HOOKS.forEach((hook) => {
strats[hook] = mergeHook;
});
export const LIFECYCLE_HOOKS = [
'beforeCreate',
'created',
'beforeMount',
'mounted',
'beforeUpdate',
'updated',
'beforeDestroy',
'destroyed',
'activated',
'deactivated',
'errorCaptured'
]
现在看一下到目前为止哪些地方调用了mergeOptions
:
- Vue.prototype._init 方法中,也就是实例化Vue的时候,也就是第一次调用
new Vue()
的时候
vm.$options = mergeOptions(vm.constructor.options, options, vm)
- Vue.extends 方法中,也就是实例化组件时候
Vue.extend = function (extendOptions) {
const Super = this;
Sub.options = mergeOptions(Super.options, extendOptions);
}
这两类都是把类的options属性和传入的options做merge。
这样看来,如果直接调用Vue.mixin()
那么后面所有的组件的options中都具备了mixin
网友评论