从零开始的Vue世界-05

207 阅读1分钟

本章主要解释Vue中mixin的原理

全局方法mixin

import {mergeOptions} from './utils'
export function initGlobalAPI(Vue) {
    // 静态方法
    Vue.options = {}
    Vue.mixin = function (mixin) {
        // 我们期望将用户的选项和 全局的options进行合并 '
        this.options = mergeOptions(this.options, mixin);
        return this;
    }
}

核心方法meageOptions

const strats = {};
const LIFECYCLE = [
    'beforeCreate',
    'created'
]
LIFECYCLE.forEach(hook => {
    strats[hook] = function (p, c) {
        //  {} {created:function(){}}   => {created:[fn]}
        // {created:[fn]}  {created:function(){}} => {created:[fn,fn]}
        if (c) { // 如果儿子有 父亲有   让父亲和儿子拼在一起
            if (p) {
                return p.concat(c);
            } else {
                return [c]; // 儿子有父亲没有 ,则将儿子包装成数组
            }
        } else {
            return p; // 如果儿子没有则用父亲即可
        }
    }
})

 

export function mergeOptions(parent, child) {
    const options = {};
    for (let key in parent) { // 循环老的  {}
        mergeField(key);
    }
    for (let key in child) { // 循环老的   {a:1}
        if (!parent.hasOwnProperty(key)) {
            mergeField(key);
        }
    }
    function mergeField(key) {
        // 策略模式 用策略模式减少if /else
        if (strats[key]) {
            options[key] = strats[key](parent[key], child[key])
        } else {
            // 如果不在策略中则以儿子为主
            options[key] = child[key] || parent[key]; // 优先采用儿子,在采用父亲
        }
    }
    return options;

}

初始化时调用钩子函数

 Vue.prototype._init = function (options) { // 用于初始化操作
        // vue  vm.$options 就是获取用户的配置 
        const vm = this;

        vm.$options = mergeOptions(this.constructor.options,options); // 将用户的选项挂载到实例上
        callHook(vm,'beforeCreate'); // 内部调用的是beforeCreate 写错了就不执行了
        // 初始化状态
        initState(vm);
        callHook(vm,'created');
}

调用函数

export function callHook(vm,hook){ // 调用钩子函数
    const handlers = vm.$options[hook];
    if(handlers){
        handlers.forEach(handler=>handler.call(vm))
    }
}

这样自己的函数就会在对应的生命周期中执行,同时自己的属性也会赋给option。