Mixin 原理
export function initGlobalAPI(Vue) {
Vue.options = {};
Vue.mixin = function (mixin) {
// 将属性合并到 Vue.options 上
this.options = mergeOptions(this.options, mixin);
return this;
}
}
合并生命周期
export const LIFECYCLE_HOOKS = [
'beforeCreate',
'created',
'beforeMount',
'mounted',
'beforeUpdate',
'updated',
'beforeDestroy',
'destroyed',
]
const strats = {};
// 生命周期的合并策略(合并为一个数组,并且 mixin 的钩子排前,实例钩子排后)
function mergeHook(parentVal, childValue) {
if (childValue) {
if (parentVal) {
return parentVal.concat(childValue);
} else {
return [childValue]
}
} else {
return parentVal;
}
}
LIFECYCLE_HOOKS.forEach(hook => {
strats[hook] = mergeHook
})
// 组件以 孙子.__proto__ = 儿子、儿子.__proto__ = 父亲 原型链的方式继承
function mergeAssets(parentVal, childVal) {
const res = Object.create(parentVal) // res.__proto__ = parentVal
if (childVal) {
for (let key in childVal) {
res[key] = childVal[key];
}
}
return res;
}
strats.components = mergeAssets
export function mergeOptions(parent, child) {
// 1.组件先将自己的 extends、mixin 的组件扩展属性与父属性合并(components 合并)
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)
}
}
}
// 2.再用之前合并后的结果,与自身的属性进行合并
const options = {}
for (let key in parent) {
mergeField(key)
}
for (let key in child) {
if (!parent.hasOwnProperty(key)) {
mergeField(key);
}
}
function mergeField(key) {
if (strats[key]) {
options[key] = strats[key](parent[key], child[key]);
} else {
if (typeof parent[key] == 'object' && typeof child[key] == 'object') {
options[key] = {
...parent[key],
...child[key]
}
} else {
options[key] = child[key];
}
}
}
return options
}
调用生命周期
export function callHook(vm, hook) {
const handlers = vm.$options[hook];
if (handlers) {
for (let i = 0; i < handlers.length; i++) {
handlers[i].call(vm);
}
}
}
初始化流程中调用生命周期
Vue.prototype._init = function (options) {
const vm = this;
vm.$options = mergeOptions(vm.constructor.options, options);
// 初始化状态
callHook(vm, 'beforeCreate');
initState(vm);
callHook(vm, 'created');
if (vm.$options.el) {
vm.$mount(vm.$options.el);
}
}
打赏作者
您的打赏是我前进的动力
微信
支付宝
响应式
上一篇
评论