前言
本章项目地址- 拿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);
}
}