vue2核心原理(简易) - 生命周期初次实现 + Vue.mixin笔记

1,163 阅读1分钟

前言

  • 本章项目地址
  • 拿beforeCreate举例, 在new实例将所有beforeCreate(可能多个,如Vue.mixin)放到一个数组当中 在其数据初始化前循环调用
  • 生命周期是在某个时刻就将其调用

正题

示例

<div id="app"></div>

<script>
Vue.mixin({
    beforeCreate() {
        console.log('beforeCreate1')
    }
}).mixin({
    beforeCreate() {
        console.log('beforeCreate2')
    }
})

let vm = new Vue({
    data() {
        return {
            author: 'xxx'
        }
    },

    beforeCreate() {
        console.log('beforeCreate3')
    }
})
vm.$mount('#app')
</script>

呈现效果

Vue.mixin

Vue.mixin 以及 合并方法(mergeOptions) 先将Vue.mixin传入的对象进行合并, 并放到Vue.options上, 方便new Vue与组件内的options合并

  • 合并思想如下
  • {} + {beforeCreate:Fn} => {beforeCreate:[fn]}
  • {beforeCreate:[fn]} + {beforeCreate:fn} => {beforeCreate:[fn,fn]}
/** 存放全局的配置 每个组件初始化的时候 都要与其合并 */
Vue.options = {}

Vue.mixin = function (options) {
    this.options = mergeOptions(this.options, options)
    // Vue.mixin().mixin()
    return this
}
export function isObject(data) {
    return typeof data === 'object' && data !== null
}

/** 存放各种策略 */
let strats = {}

/**
 * @description 生命周期 hook方法
 */
function mergeHook(parentVal, childVal) {
    if (childVal) {
        if (parentVal) {
            return parentVal.concat(childVal)
        } else {
            return [childVal]
        }
    } else {
        return parentVal
    }
}

let lifeCycleHooks = [
    'beforeCreate',
    'created',
    'beforeMount',
    'mounted',
    'beforeUpdate',
    'updated',
    'beforeDestroy',
    'destroyed',
]
lifeCycleHooks.forEach(hook => {
    strats[hook] = mergeHook
})

/**
 * @description 合并Vue.options
 */
export function mergeOptions(parent, child) {
    const options = {}

    for (let key in parent) {
        mergeField(key)
    }

    for (let key in child) {
        if (parent.hasOwnProperty(key)){
            continue
        }
        mergeField(key)
    }

    function mergeField(key) {
        let parentVal = parent[key]
        let childVal = child[key]

        if (strats[key]) {
            options[key] = strats[key](parentVal, childVal)
        } else {
            if (isObject(parentVal) && isObject(childVal)) {
                options[key] = { ...parentVal, ...childVal }
            } else {
                options[key] = parentVal || childVal
            }
        }

    }

    return options
}

再将new Vue({})传入的对象与vm.constructor.options进行合并

function Vue (options) {
    /** 初始化 */
    this._init(options)
}
/**
 * @description callhook 生命执行方法
 */
export function callHook(vm, hook) {
    let 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)
    console.log('vm.$options: ', vm.$options);
	
    // 调用生命周期的beforeCreate
    callHook(vm, 'beforeCreate')

    /** 数据初始化 */
    initState(vm)

    callHook(vm, 'created')

    /** compile */
    if(vm.$options.el){
        vm.$mount(vm.$options.el);
    }
}

下一章vue2核心原理(简易) - 组件(Vue.component)的实现