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);
    }
}
打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. Mixin 原理
  2. 2. 合并生命周期
  3. 3. 调用生命周期
  4. 4. 初始化流程中调用生命周期